import java.awt.Frame; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.security.GeneralSecurityException; import java.security.ProviderException; import javax.net.ssl.SSLHandshakeException; import javax.swing.JApplet; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.apache.commons.httpclient.HttpException; import netscape.javascript.JSObject; import br.gov.serpro.cert.DigitalCertificate; import br.gov.serpro.setup.Setup; import br.gov.serpro.ui.DialogBuilder; /** * GUI que realiza o login com certificados A1 e A3 ou login com usuário e senha no expresso. * Esta classe estende a classe JApplet * @author Mário César Kolling - mario.kolling@serpro.gov.br */ public class LoginApplet extends JApplet{ /** * Valor gerado aleatoriamente */ //TODO: Alterar a cor e fonte dos labels e das caixas de texto e senha. private static final long serialVersionUID = -6204158613173951516L; //private PinCodePanel pinPanel; //private LoginPanel loginPanel; //private PinCodePanel alreadyLoadedPanel; //private int useCertificate = DigitalCertificate.KEYSTORE_DETECTED; // private String uid; private DigitalCertificate dc; private Setup setup; /* (non-Javadoc) * @see java.applet.Applet#init() */ public void init() { super.init(); this.setSize(0, 0); this.setup = new Setup(this); this.setup.addLanguageResource("ExpressoCertLoginMessages"); } /* (non-Javadoc) * @see java.applet.Applet#start() */ @Override public void start() { super.start(); int useCertificate = DigitalCertificate.KEYSTORE_NOT_DETECTED; boolean tryAgain = true; do { // Cria uma instância de DigitalCertificate e a inicializa this.dc = new DigitalCertificate(this.getDocumentBase(), setup); useCertificate = dc.init(); String[] returnCode = null; try { switch (useCertificate){ case DigitalCertificate.KEYSTORE_DETECTED: // Mostra PinNeedeDialog. //tryAgain = false; String pin = DialogBuilder.showPinDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), this.setup); if (pin != null) { dc.openKeyStore(pin.toCharArray()); returnCode = dc.getCredentials(pin); // se chegou aqui, keystore foi acessada e as credenciais do usuário foram recuperadas //tryAgain = false; assert (returnCode != null): "Valor de returnCode não pode ser nulo"; //this.dc.destroy(); // Faz o login if (setup.getParameter("debug").equalsIgnoreCase("true")) { System.out.println("Código de retorno: " + returnCode[0].trim()); } if (Integer.parseInt(returnCode[0].trim()) == 0){ tryAgain = false; // Pega usuário e senha de credentials[1] e credentials[2], respectivamente // adiciona na página e faz o submit. JSObject document = (JSObject) JSObject.getWindow( this ).getMember("document"); JSObject loginForm = (JSObject) document.getMember("flogin"); JSObject loginField = (JSObject) loginForm.getMember("user"); loginField.setMember("value", returnCode[1].trim()); JSObject passwdField = (JSObject) loginForm.getMember("passwd"); passwdField.setMember("value", returnCode[2].trim()); loginForm.call("submit", null); Thread.yield(); } else if (Integer.parseInt(returnCode[0].trim()) == 6){ tryAgain = false; if (setup.getParameter("debug").equalsIgnoreCase("true")) { System.out.println("Mensagem de retorno: " + returnCode[1].trim()); } //JOptionPane.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), credentials[1]); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), returnCode[1].trim(), this.setup); String redirect = this.getCodeBase().toExternalForm() + "login.php?cd=98&ts=202"; try { this.getAppletContext().showDocument(new URL(redirect)); } catch (MalformedURLException e) { // TODO Bloco catch gerado automaticamente if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ e.printStackTrace(); } } } else { tryAgain = true; dc.destroy(); System.gc(); if (setup.getParameter("debug").equalsIgnoreCase("true")) { System.out.println("Mensagem de retorno: " + returnCode[1].trim()); } // Mostra mensagem de erro para o usuário //JOptionPane.showMessageDialog(this, credentials[1]); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), returnCode[1].trim(), this.setup); Thread.yield(); } } else { tryAgain = false; String redirect = this.getCodeBase().toExternalForm() + "login.php"; try { this.getAppletContext().showDocument(new URL(redirect)); } catch (MalformedURLException e) { // TODO Bloco catch gerado automaticamente if (setup.getParameter("debug").equalsIgnoreCase("true")) { e.printStackTrace(); } } } break; /* case DigitalCertificate.KEYSTORE_ALREADY_LOADED: // Mostra PinNotNeededDialog tryAgain = false; //Verifica na página se operação anterior foi um logout JSObject document = (JSObject) JSObject.getWindow( this ).getMember("document"); JSObject loginForm = (JSObject) document.getMember("flogin"); JSObject loginField = (JSObject) loginForm.getMember("cd"); String cdValue = (String) loginField.getMember("value"); int cd = 0; if (cdValue.length() != 0){ cd = Integer.parseInt(cdValue); } // Se não foi logout prossegue com o login, senão pára tudo if (cd != 1 && cd != 5){ DialogBuilder.showPinNotNeededDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this)); dc.openKeyStore(null); returnCode = dc.getCredentials(""); // se chegou aqui, keystore foi acessada e as credenciais do usuário foram recuperadas assert (returnCode != null): "Valor de returnCode não pode ser nulo"; // Faz o login doLogin(returnCode); } else if (cd == 5){ JOptionPane.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), "Não foi possível realizar o Logon com certificado!"); // Redireciona para a tela de login String redirect = this.getCodeBase().toExternalForm() + "login.php"; try { this.getAppletContext().showDocument(new URL(redirect)); } catch (MalformedURLException e) { // TODO Bloco catch gerado automaticamente e.printStackTrace(); } } //DialogBuilder.showPinNotNeededDialog(findParentframe()); break; */ default: // Mostra Diálogo dizendo que token não foi encontrado // ou repositório de chaves públicas não foi configurado. // Tentar carregar token/keystore novamente? / Logon sem certificado digital? tryAgain = false; if (setup.getParameter("debug").equalsIgnoreCase("true")) { System.out.println("não achou token"); } dc.destroy(); System.gc(); String redirect = this.getCodeBase().toExternalForm() + "login.php"; try { this.getAppletContext().showDocument(new URL(redirect)); } catch (MalformedURLException e) { // TODO Bloco catch gerado automaticamente if (setup.getParameter("debug").equalsIgnoreCase("true")) { e.printStackTrace(); } } //int resultado = JOptionPane.showConfirmDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), // "Deseja tentar novamente?", // "Token não foi encontrado!", // JOptionPane.OK_CANCEL_OPTION, // JOptionPane.QUESTION_MESSAGE); //if (resultado == JOptionPane.OK_OPTION){ // tryAgain = true; //} //else { //} // if () { // tryAgain = true; //} } } catch (SSLHandshakeException e){ if (setup.getParameter("debug").equalsIgnoreCase("true")) { e.printStackTrace(); } dc.destroy(); System.gc(); //JOptionPane.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), "Não foi possível validar o certificado do servidor!"); //DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), // "Não foi possível validar o certificado do servidor!", this.setup); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), this.setup.getLang("ExpressoCertLoginMessages", "LoginApplet001"), this.setup); Thread.yield(); tryAgain = true; } catch (HttpException e) { if (setup.getParameter("debug").equalsIgnoreCase("true")) { e.printStackTrace(); } tryAgain = true; Thread.yield(); } catch (GeneralSecurityException e){ if (setup.getParameter("debug").equalsIgnoreCase("true")) { e.printStackTrace(); } //DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), // "Algum erro ocorreu ao realizar o logon!", this.setup); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), this.setup.getLang("ExpressoCertLoginMessages", "LoginApplet002"), this.setup); Thread.yield(); tryAgain = true; } catch (IOException e) { dc.destroy(); System.gc(); if (setup.getParameter("debug").equalsIgnoreCase("true")) { e.printStackTrace(); } //System.out.println("Classe que originou o erro de IO: " + e.getClass().getCanonicalName());; Throwable cause = null; if ((cause = e.getCause()) != null){ if (cause instanceof javax.security.auth.login.LoginException){ //DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), "PIN incorreto!", this.setup); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), this.setup.getLang("ExpressoCertLoginMessages", "LoginApplet003"), this.setup); } else { if (setup.getParameter("debug").equalsIgnoreCase("true")) { System.out.println("Exception lançada: " + cause.getClass().getCanonicalName()); } } } else { if (e instanceof java.net.ConnectException){ //DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), // "Não foi possível fazer a conexão com o servidor do Expresso.\n" + // "Verifique suas configurações de rede/proxy.", this.setup); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), this.setup.getLang("ExpressoCertLoginMessages", "LoginApplet004"), this.setup); } else { if (setup.getParameter("debug").equalsIgnoreCase("true")) { System.out.println("Exception lançada: " + e.getClass().getCanonicalName()); } } } Thread.yield(); tryAgain = true; } catch (ProviderException e) { // Tentar novamente / cancel //JOptionPane.showMessageDialog(this, "Token foi removido! Favor inserir seu token"); dc.destroy(); System.gc(); if (setup.getParameter("debug").equalsIgnoreCase("true")) { e.printStackTrace(); } /* JOptionPane optionPane = new JOptionPane("Token foi removido\nDeseja tentar carregá-lo novamente?", JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); JDialog dialog = new JDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), true); dialog.setContentPane(optionPane); //Posicionando no centro da tela. Dimension mySize = dialog.getSize(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); dialog.setLocation(screenSize.width/2 - (mySize.width/2), screenSize.height/2 - (mySize.height/2)); dialog.setVisible(true); Object selectedValue = optionPane.getValue(); if (selectedValue == null){ } else { if (selectedValue instanceof Integer){ Integer } } */ int resultado = DialogBuilder.showConfirmDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), //"Deseja tentar carregá-lo novamente?", this.setup.getLang("ExpressoCertLoginMessages", "LoginApplet005"), JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, this.setup); /* int resultado = JOptionPane.showConfirmDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), "Deseja tentar carregá-lo novamente?", "Token foi removido!", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); */ if (resultado == JOptionPane.OK_OPTION){ tryAgain = true; } else { tryAgain = false; } Thread.yield(); } } while (tryAgain); // chama o método que cria a interface na thread de lançamento de eventos (Event Dispatching Thread). //try //{ // SwingUtilities.invokeAndWait(new Runnable(){ /* (non-Javadoc) * @see java.lang.Runnable#run() */ // public void run() { // createGUI(); // } // }); //} catch (Exception e){ // System.out.println("Método createGUI não pôde ser carregado: " + e.getMessage()); //} } /* public void doLogin(String[] credentials){ if (Integer.valueOf(credentials[0]) == 0){ // Pega usuário e senha de credentials[1] e credentials[2], respectivamente // adiciona na página e faz o submit. JSObject document = (JSObject) JSObject.getWindow( this ).getMember("document"); JSObject loginForm = (JSObject) document.getMember("flogin"); JSObject loginField = (JSObject) loginForm.getMember("user"); loginField.setMember("value", credentials[1]); JSObject passwdField = (JSObject) loginForm.getMember("passwd"); passwdField.setMember("value", credentials[2]); loginForm.call("submit", null); } else if (Integer.valueOf(credentials[0]) == 6){ //JOptionPane.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), credentials[1]); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), credentials[1]); String redirect = this.getCodeBase().toExternalForm() + "login.php?cd=98&ts=202"; try { this.getAppletContext().showDocument(new URL(redirect)); } catch (MalformedURLException e) { // TODO Bloco catch gerado automaticamente e.printStackTrace(); } } else { // Mostra mensagem de erro para o usuário //JOptionPane.showMessageDialog(this, credentials[1]); DialogBuilder.showMessageDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this), credentials[1]); } } */ /** * Destrói a Applet, executando códigos para desregistrar tokens, keystores, etc. */ @Override public void stop() { //super.destroy(); if (setup.getParameter("debug").equalsIgnoreCase("true")) { System.out.println("Finalizando Applet de Login!"); } this.dc.destroy(); this.dc = null; //Component[] components = this.getComponents(); //for (Component component : components){ // this.remove(component); // component = null; //} System.gc(); } /** * Cria a interface e seleciona o Painel que será exibido de acordo com o parâmetro useCertificate */ /* private void createGUI(){ this.setLayout(new FlowLayout()); this.getContentPane().setBackground(Color.WHITE); JSObject document = (JSObject) JSObject.getWindow( this ).getMember("document"); JSObject loginForm = (JSObject) document.getMember("flogin"); JSObject loginField = (JSObject) loginForm.getMember("user"); uid = loginField.getMember("value").toString(); pinPanel = new PinCodePanel(uid, true); // mostra pinCodeField alreadyLoadedPanel = new PinCodePanel(uid, false); // não mostra pinCodeField loginPanel = new LoginPanel(uid); switch (useCertificate){ case DigitalCertificate.KEYSTORE_NOT_DETECTED: // Mostra interface de login com usuário e senha this.getContentPane().add(loginPanel); break; case DigitalCertificate.KEYSTORE_ALREADY_LOADED: // Mostra interface de login sem pedir o pin this.getContentPane().add(alreadyLoadedPanel); break; default: // Mostra interface de login pedindo o pin this.getContentPane().add(pinPanel); } this.setVisible(true); } */ /** * Ação executada quando o Botão cancel de PinPanel for pressionado * */ /* private void cancelButtonActionPerformed(){ pinPanel.setVisible(false); this.remove(pinPanel); this.add(loginPanel); loginPanel.setVisible(true); this.setVisible(true); pinPanel.clearPasswordField(); } */ /** * Ação realizada quando o usuário pressiona o botão Ok ou Prossegir * nas telas de login com pin ou sem o pin, respectivamente * */ /* private void okButtonActionPerformed(){ // atribui o valor da senha para o atributo Pin char[] pin = pinPanel.getPin(); String[] returnCode = null; // abre a keystore com o pin e recupera as credenciais do usuário try { dc.openKeyStore(pin); returnCode = dc.getCredentials(new String(pin)); assert (returnCode != null): "Valor de returnCode não pode ser nulo"; if (Integer.valueOf(returnCode[0]) == 0){ // Pega usuário e senha de returnCode[1] e returnCode[2], respectivamente // adiciona na página e faz o submit. JSObject document = (JSObject) JSObject.getWindow( this ).getMember("document"); JSObject loginForm = (JSObject) document.getMember("flogin"); JSObject loginField = (JSObject) loginForm.getMember("user"); loginField.setMember("value", returnCode[1]); JSObject passwdField = (JSObject) loginForm.getMember("passwd"); passwdField.setMember("value", returnCode[2]); this.pinPanel.clearPasswordField(); loginForm.call("submit", null); } else { // Mostra mensagem de erro para o usuário showGetCredentialsError(returnCode[1]); } } catch (SSLHandshakeException e){ e.printStackTrace(); JOptionPane.showMessageDialog(this, "Não foi possível validar o certificado do servidor!"); } catch (HttpException e) { e.printStackTrace(); } catch (GeneralSecurityException e){ e.printStackTrace(); } catch (IOException e) { JOptionPane.showMessageDialog(this, "Senha não confere!"); } catch (ProviderException e) { JOptionPane.showMessageDialog(this, "Token foi removido!"); } finally { this.pinPanel.clearPasswordField(); } } */ /** * Ação realizada quando o usuário pressiona o botão acessar na * tela de login com usuário e senha * */ /* private void acessarButtonActionPerformed(){ // Pega usuário e senha dos campos tfUsername e pfPasswd, respectivamente, // adiciona na página e faz o submit. String username = this.loginPanel.tfUsername.getText(); String passwd = String.valueOf(this.loginPanel.pfPasswd.getPassword()); JSObject document = (JSObject) JSObject.getWindow( this ).getMember("document"); JSObject loginForm = (JSObject) document.getMember("flogin"); JSObject loginField = (JSObject) loginForm.getMember("user"); loginField.setMember("value", username); JSObject passwdField = (JSObject) loginForm.getMember("passwd"); passwdField.setMember("value", passwd); this.loginPanel.clearPasswordField(); loginForm.call("submit", null); } */ /** * Mostra mensagem "Campo PIN não foi preenchido!" quando o botão Ok for pressionado * e o campo pin estiver vazio * */ /* private void okButtonPinEmpty(){ JOptionPane.showMessageDialog(this, "Campo PIN não foi preenchido!"); } */ /** * Mostra mensagem de erro recebida de dc.getCredentials(); * TODO: Mudar este método para ser mais genérico... Todas as mensagens de erro devem ser passadas para este * método para serem exibidas. * @param errorMsg Mensagem de erro que deve ser exibida */ /* private void showGetCredentialsError(String errorMsg){ JOptionPane.showMessageDialog(this, errorMsg); } private final class PinCodePanel extends JPanel implements ActionListener{ */ /** * Gerado automaticamente */ /* private static final long serialVersionUID = 1003857725229120014L; JPanel pNorte, pCentro, pSul; JButton btOk, btCancel; JLabel lTitle, lPin; JPasswordField pfPin; // TODO: Implementar um construtor default (sem parâmetros); public PinCodePanel(String uid, boolean showPinField){ this.setLayout(new BorderLayout()); Dimension panelsDimension = new Dimension(300, 42); Dimension fieldsDimension = new Dimension(80, 20); pNorte = new JPanel(new FlowLayout(FlowLayout.CENTER)); pNorte.setBackground(Color.WHITE); pNorte.setPreferredSize(panelsDimension); pCentro = new JPanel(new FlowLayout(FlowLayout.CENTER)); pCentro.setBackground(Color.WHITE); pCentro.setPreferredSize(panelsDimension); pSul = new JPanel(new FlowLayout(FlowLayout.CENTER)); pSul.setBackground(Color.WHITE); pSul.setPreferredSize(panelsDimension); JPanel pTitle = new JPanel(new GridLayout(2, 0)); pTitle.setBackground(Color.WHITE); JLabel lTitle2 = null; if (showPinField){ lTitle = new JLabel("Entre com o seu PIN:"); lTitle.setHorizontalTextPosition(SwingConstants.CENTER); pfPin = new JPasswordField(20); pfPin.setPreferredSize(fieldsDimension); pfPin.addActionListener(this); pfPin.setActionCommand("ok"); pCentro.add(pfPin); btOk = new JButton("Ok"); btCancel = new JButton("Cancel"); } else { lTitle = new JLabel("Token inserido e desbloqueado"); lTitle.setHorizontalTextPosition(SwingConstants.CENTER); lTitle2 = new JLabel(" pelo usuário " + uid + " foi detectado:"); lTitle2.setHorizontalTextPosition(SwingConstants.CENTER); btOk = new JButton("Prossegir"); } JPanel pTitle1 = new JPanel(new FlowLayout(FlowLayout.CENTER)); pTitle1.setPreferredSize(new Dimension(300, 20)); pTitle1.setBackground(Color.WHITE); pTitle1.add(lTitle); pTitle.add(pTitle1); if (lTitle2 != null) { JPanel pTitle2 = new JPanel(new FlowLayout(FlowLayout.CENTER)); pTitle2.setPreferredSize(new Dimension(300,20)); pTitle2.setBackground(Color.WHITE); pTitle.add(pTitle2); pTitle2.add(lTitle2); } pNorte.add(pTitle); btOk.setMnemonic(KeyEvent.VK_ENTER); btOk.setActionCommand("ok"); btOk.addActionListener(this); pSul.add(btOk); if (btCancel != null){ btCancel.setActionCommand("cancel"); btCancel.addActionListener(this); pSul.add(btCancel); } this.add(pNorte, BorderLayout.NORTH); this.add(pCentro, BorderLayout.CENTER); this.add(pSul, BorderLayout.SOUTH); } // design ruim!!! azar :-S public char[] getPin() { if (pfPin == null){ return null; } return pfPin.getPassword(); } void clearPasswordField(){ if (pfPin != null){ pfPin.setText(""); } } public void actionPerformed(ActionEvent evt) { String command = evt.getActionCommand(); // Atribui o valor digitado para o campo // senha e esconde a interface e assina o certificado if (command.equals("ok")){ if (pfPin != null && pfPin.getPassword().length <= 0){ // Mostra um aviso de que o campo PIN não foi preenchido okButtonPinEmpty(); } else { okButtonActionPerformed(); } } else if (command.equals("cancel")){ cancelButtonActionPerformed(); } } } private final class LoginPanel extends JPanel implements ActionListener{ */ /** * */ /* private static final long serialVersionUID = -8604718192554937222L; JButton btAcessar; JTextField tfUsername; JPasswordField pfPasswd; public LoginPanel(String uid){ this.setLayout(new BorderLayout()); JPanel panelCredentials = new JPanel(new GridLayout(2, 0)); panelCredentials.setBackground(Color.WHITE); panelCredentials.setPreferredSize(new Dimension(280, 84)); JPanel panelUsername = new JPanel(new FlowLayout(FlowLayout.CENTER)); panelUsername.setBackground(Color.WHITE); panelUsername.setPreferredSize(new Dimension(300, 42)); JLabel labelUsername = new JLabel("Usuário"); panelUsername.add(labelUsername); labelUsername.setPreferredSize(new Dimension(100, 40)); tfUsername = new JTextField(15); tfUsername.setText(uid); panelUsername.add(tfUsername); JPanel panelPasswd = new JPanel(new FlowLayout(FlowLayout.CENTER)); panelPasswd.setPreferredSize(new Dimension(300, 42)); JLabel labelPasswd = new JLabel("Senha"); panelPasswd.add(labelPasswd); panelPasswd.setBackground(Color.WHITE); labelPasswd.setPreferredSize(new Dimension(100, 20)); pfPasswd = new JPasswordField(15); panelPasswd.add(pfPasswd); panelCredentials.add(panelUsername); panelCredentials.add(panelPasswd); this.add(panelCredentials, BorderLayout.CENTER); btAcessar = new JButton("Acessar"); btAcessar.setActionCommand("acessar"); btAcessar.addActionListener(this); JPanel panelBtAcessar = new JPanel(new FlowLayout(FlowLayout.CENTER)); panelBtAcessar.setBackground(Color.WHITE); panelBtAcessar.setPreferredSize(new Dimension(300, 42)); panelBtAcessar.add(btAcessar); this.add(panelBtAcessar, BorderLayout.SOUTH); this.setVisible(true); } public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("acessar")){ acessarButtonActionPerformed(); } } void clearPasswordField(){ pfPasswd.setText(""); } } */ }