    public String preProcessHTML(String uri) {
        final StringBuffer buf = new StringBuffer();
        try {
            HTMLDocument doc = new HTMLDocument() {

                public HTMLEditorKit.ParserCallback getReader(int pos) {
                    return new HTMLEditorKit.ParserCallback() {

                        public void handleText(char[] data, int pos) {
                            buf.append(data);
                            buf.append('\n');
                        }
                    };
                }
            };
            URL url = new URI(uri).toURL();
            URLConnection conn = url.openConnection();
            Reader rd = new InputStreamReader(conn.getInputStream());
            new ParserDelegator().parse(rd, doc.getReader(0), Boolean.TRUE);
        } catch (MalformedURLException e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
        } catch (URISyntaxException e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
        }
        return buf.toString();
    }


    public static void copyFile(File in, File out) throws IOException {
        FileChannel inChannel = new FileInputStream(in).getChannel();
        FileChannel outChannel = new FileOutputStream(out).getChannel();
        try {
            inChannel.transferTo(0, inChannel.size(), outChannel);
        } catch (IOException e) {
            throw e;
        } finally {
            if (inChannel != null) inChannel.close();
            if (outChannel != null) outChannel.close();
        }
    }


    public static void copyTo(File src, File dest) throws IOException {
        if (src.equals(dest)) throw new IOException("copyTo src==dest file");
        FileOutputStream fout = new FileOutputStream(dest);
        InputStream in = new FileInputStream(src);
        IOUtils.copyTo(in, fout);
        fout.flush();
        fout.close();
        in.close();
    }


    private void getRandomGUID(boolean secure) throws NoSuchAlgorithmException {
        MessageDigest md5 = null;
        StringBuffer sbValueBeforeMD5 = new StringBuffer();
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            System.out.println("Error: " + e);
            throw e;
        }
        try {
            long time = System.currentTimeMillis();
            long rand = 0;
            if (secure) {
                rand = mySecureRand.nextLong();
            } else {
                rand = myRand.nextLong();
            }
            sbValueBeforeMD5.append(s_id);
            sbValueBeforeMD5.append(":");
            sbValueBeforeMD5.append(Long.toString(time));
            sbValueBeforeMD5.append(":");
            sbValueBeforeMD5.append(Long.toString(rand));
            valueBeforeMD5 = sbValueBeforeMD5.toString();
            md5.update(valueBeforeMD5.getBytes());
            byte[] array = md5.digest();
            StringBuffer sb = new StringBuffer();
            for (int j = 0; j < array.length; ++j) {
                int b = array[j] & 0xFF;
                if (b < 0x10) sb.append('0');
                sb.append(Integer.toHexString(b));
            }
            valueAfterMD5 = sb.toString();
        } catch (Exception e) {
            System.out.println("Error:" + e);
        }
    }


    public void mode(String env) {
        String path = this.envs.get(env);
        InputStream in = null;
        try {
            URL url = ResourceUtil.getResourceNoException(path);
            if (url == null) {
                throw new IllegalEnvironmentException(env);
            }
            load(URLUtil.openStream(url));
        } catch (IOException e) {
            throw new IllegalEnvironmentException(env, e);
        } finally {
            StreamUtil.close(in);
        }
    }


    private static void copyFile(String fromFile, String toFile) throws Exception {
        FileInputStream from = null;
        FileOutputStream to = null;
        try {
            from = new FileInputStream(fromFile);
            to = new FileOutputStream(toFile);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = from.read(buffer)) != -1) to.write(buffer, 0, bytesRead);
        } finally {
            if (from != null) try {
                from.close();
            } catch (IOException e) {
                ;
            }
            if (to != null) try {
                to.close();
            } catch (IOException e) {
                ;
            }
        }
    }


    private String md5(String pass) {
        StringBuffer enteredChecksum = new StringBuffer();
        byte[] digest;
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
            md5.update(pass.getBytes(), 0, pass.length());
            digest = md5.digest();
            for (int i = 0; i < digest.length; i++) {
                enteredChecksum.append(toHexString(digest[i]));
            }
        } catch (NoSuchAlgorithmException e) {
            log.error("Could not create MD5 hash!");
            log.error(e.getLocalizedMessage());
            log.error(e.getStackTrace());
        }
        return enteredChecksum.toString();
    }


    public void createMd5Hash() {
        try {
            String vcardObject = new ContactToVcard(TimeZone.getTimeZone("UTC"), "UTF-8").convert(this);
            MessageDigest m = MessageDigest.getInstance("MD5");
            m.update(vcardObject.getBytes());
            this.md5Hash = new BigInteger(m.digest()).toString();
            if (log.isTraceEnabled()) {
                log.trace("Hash is:" + this.md5Hash);
            }
        } catch (ConverterException ex) {
            log.error("Error creating hash:" + ex.getMessage());
        } catch (NoSuchAlgorithmException noSuchAlgorithmException) {
            log.error("Error creating hash:" + noSuchAlgorithmException.getMessage());
        }
    }


    public static void createZipFromDataset(String localResourceId, File dataset, File metadata) {
        CommunicationLogger.warning("System entered ZipFactory");
        try {
            String tmpDir = System.getProperty("java.io.tmpdir");
            String outFilename = tmpDir + "/" + localResourceId + ".zip";
            CommunicationLogger.warning("File name: " + outFilename);
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFilename));
            byte[] buf = new byte[1024];
            FileInputStream in = new FileInputStream(dataset);
            out.putNextEntry(new ZipEntry(dataset.getName()));
            int len;
            while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
            in = new FileInputStream(metadata);
            out.putNextEntry(new ZipEntry(metadata.getName()));
            while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
            out.closeEntry();
            in.close();
            out.close();
        } catch (IOException e) {
            System.out.println("IO EXCEPTION: " + e.getMessage());
        }
    }


    public boolean verify(String digest, String password) throws NoSuchAlgorithmException {
        String alg = null;
        int size = 0;
        if (digest.regionMatches(true, 0, "{CRYPT}", 0, 7)) {
            digest = digest.substring(7);
            return UnixCrypt.matches(digest, password);
        } else if (digest.regionMatches(true, 0, "{SHA}", 0, 5)) {
            digest = digest.substring(5);
            alg = "SHA-1";
            size = 20;
        } else if (digest.regionMatches(true, 0, "{SSHA}", 0, 6)) {
            digest = digest.substring(6);
            alg = "SHA-1";
            size = 20;
        } else if (digest.regionMatches(true, 0, "{MD5}", 0, 5)) {
            digest = digest.substring(5);
            alg = "MD5";
            size = 16;
        } else if (digest.regionMatches(true, 0, "{SMD5}", 0, 6)) {
            digest = digest.substring(6);
            alg = "MD5";
            size = 16;
        }
        MessageDigest msgDigest = MessageDigest.getInstance(alg);
        byte[][] hs = split(Base64.decode(digest.toCharArray()), size);
        byte[] hash = hs[0];
        byte[] salt = hs[1];
        msgDigest.reset();
        msgDigest.update(password.getBytes());
        msgDigest.update(salt);
        byte[] pwhash = msgDigest.digest();
        return msgDigest.isEqual(hash, pwhash);
    }


    public String generateDigest(String password, String saltHex, String algorithm) throws NoSuchAlgorithmException {
        if (algorithm.equalsIgnoreCase("crypt")) {
            return "{CRYPT}" + UnixCrypt.crypt(password);
        } else if (algorithm.equalsIgnoreCase("sha")) {
            algorithm = "SHA-1";
        } else if (algorithm.equalsIgnoreCase("md5")) {
            algorithm = "MD5";
        }
        MessageDigest msgDigest = MessageDigest.getInstance(algorithm);
        byte[] salt = {};
        if (saltHex != null) {
            salt = fromHex(saltHex);
        }
        String label = null;
        if (algorithm.startsWith("SHA")) {
            label = (salt.length > 0) ? "{SSHA}" : "{SHA}";
        } else if (algorithm.startsWith("MD5")) {
            label = (salt.length > 0) ? "{SMD5}" : "{MD5}";
        }
        msgDigest.reset();
        msgDigest.update(password.getBytes());
        msgDigest.update(salt);
        byte[] pwhash = msgDigest.digest();
        StringBuffer digest = new StringBuffer(label);
        digest.append(Base64.encode(concatenate(pwhash, salt)));
        return digest.toString();
    }


    public static Chunk updateLastSend(Chunk c) throws Exception {
        DBConnectionManager dbm = null;
        Connection conn = null;
        PreparedStatement stmt = null;
        Chunk ret = null;
        String SQL = "UPDATE CHUNK SET SENT=? WHERE FILEHASH=? AND STARTOFF=? AND LENGTH=?";
        log.debug("update chunk last sent for chunk " + c.getHash() + " startoff " + c.getStartOffset());
        try {
            dbm = DBConnectionManager.getInstance();
            conn = dbm.getConnection("satmule");
            stmt = conn.prepareStatement(SQL);
            stmt.setDate(1, new java.sql.Date(c.getLastSend().getTime()));
            stmt.setString(2, c.getHash());
            stmt.setLong(3, c.getStartOffset());
            stmt.setLong(4, c.getSize());
            stmt.executeUpdate();
            conn.commit();
            stmt.close();
            dbm.freeConnection("satmule", conn);
        } catch (Exception e) {
            log.error("Error while updating chunk " + c.getHash() + "offset:" + c.getStartOffset() + "SQL error: " + SQL, e);
            Exception excep;
            if (dbm == null) excep = new Exception("Could not obtain pool object DbConnectionManager"); else if (conn == null) excep = new Exception("The Db connection pool could not obtain a database connection"); else {
                conn.rollback();
                excep = new Exception("SQL Error : " + SQL + " error: " + e);
                dbm.freeConnection("satmule", conn);
            }
            throw excep;
        }
        return ret;
    }


    public void download() throws IOException {
        new File(file.getPath().substring(0, file.getPath().lastIndexOf(File.separator))).mkdirs();
        URLConnection urlConnection = url.openConnection();
        size = urlConnection.getContentLength();
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
        InputStream inputStream = urlConnection.getInputStream();
        byte[] buffer = new byte[1024];
        int numRead;
        fetchedSize = 0;
        date = urlConnection.getLastModified();
        while (!failed && (numRead = inputStream.read(buffer)) != -1) {
            if (failed) {
                throw new IOException("Download manually stopped");
            }
            bufferedOutputStream.write(buffer, 0, numRead);
            fetchedSize += numRead;
            for (int n = 0, i = downloadListener.size(); n < i; n++) {
                synchronized (downloadListener.get(n)) {
                    ((DownloadListener) downloadListener.get(n)).downloadProgress(this);
                }
            }
        }
        inputStream.close();
        bufferedOutputStream.close();
        if (file.toString().endsWith(".gz") || file.toString().endsWith(".gzip")) {
            for (int n = 0, i = downloadListener.size(); n < i; n++) {
                synchronized (downloadListener.get(n)) {
                    ((DownloadListener) downloadListener.get(n)).uncompressingProgress(this);
                }
            }
            try {
                GZIPInputStream gzipInputStream = new GZIPInputStream(new FileInputStream(file));
                String fileName = file.toString().substring(0, file.toString().lastIndexOf("."));
                OutputStream outputStream = new FileOutputStream(fileName);
                byte[] unpackBuffer = new byte[1024];
                int length;
                while ((length = gzipInputStream.read(unpackBuffer)) > 0) {
                    outputStream.write(unpackBuffer, 0, length);
                }
                gzipInputStream.close();
                outputStream.close();
                file.delete();
                file = new File(fileName);
                file.setLastModified(date);
                failed = false;
                finished = true;
                for (int n = 0, i = downloadListener.size(); n < i; n++) {
                    synchronized (downloadListener.get(n)) {
                        ((DownloadListener) downloadListener.get(n)).uncompressingFinished(this);
                    }
                }
                for (int n = 0, i = downloadListener.size(); n < i; n++) {
                    synchronized (downloadListener.get(n)) {
                        ((DownloadListener) downloadListener.get(n)).downloadFinished(this);
                    }
                }
            } catch (IOException ioException) {
                file.delete();
                failed = true;
                for (int n = 0, i = downloadListener.size(); n < i; n++) {
                    synchronized (downloadListener.get(n)) {
                        ((DownloadListener) downloadListener.get(n)).exceptionWasThrown(this, ioException);
                    }
                }
            }
            try {
                Runtime.getRuntime().exec("chmod 777 " + file.getCanonicalPath());
            } catch (Exception exception) {
            }
        } else {
            failed = false;
            finished = true;
            file.setLastModified(date);
            for (int n = 0, i = downloadListener.size(); n < i; n++) {
                synchronized (downloadListener.get(n)) {
                    ((DownloadListener) downloadListener.get(n)).downloadFinished(this);
                }
            }
        }
    }


    protected String doIt() throws java.lang.Exception {
        StringBuffer sql = null;
        int no = 0;
        String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID;
        if (m_deleteOldImported) {
            sql = new StringBuffer("DELETE I_BPartner " + "WHERE I_IsImported='Y'").append(clientCheck);
            no = DB.executeUpdate(sql.toString());
            log.fine("Delete Old Impored =" + no);
        }
        sql = new StringBuffer("UPDATE I_BPartner " + "SET AD_Client_ID = COALESCE(AD_Client_ID, ").append(m_AD_Client_ID).append(")," + " AD_Org_ID = COALESCE(AD_Org_ID, 0)," + " IsActive = COALESCE(IsActive, 'Y')," + " Created = COALESCE(Created, current_timestamp)," + " CreatedBy = COALESCE(CreatedBy, 0)," + " Updated = COALESCE(Updated, current_timestamp)," + " UpdatedBy = COALESCE(UpdatedBy, 0)," + " I_ErrorMsg = ''," + " I_IsImported = 'N' " + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL");
        no = DB.executeUpdate(sql.toString());
        log.fine("Reset=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET GroupValue=(SELECT Value FROM C_BP_Group g WHERE g.IsDefault='Y'" + " AND g.AD_Client_ID=i.AD_Client_ID AND ROWNUM=1) " + "WHERE GroupValue IS NULL AND C_BP_Group_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Group Default=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET C_BP_Group_ID=(SELECT C_BP_Group_ID FROM C_BP_Group g" + " WHERE i.GroupValue=g.Value AND g.AD_Client_ID=i.AD_Client_ID ORDER BY g.IsDefault DESC LIMIT 1) " + "WHERE C_BP_Group_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Group=" + no);
        sql = new StringBuffer("UPDATE I_BPartner " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'" + getMsg("ImportBPInvalidGroup") + ". ' " + "WHERE C_BP_Group_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.config("Invalid Group=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET CountryCode=(SELECT CountryCode FROM C_Country c WHERE c.isactive='Y'" + " AND c.AD_Client_ID IN (0, i.AD_Client_ID) AND ROWNUM=1) " + "WHERE CountryCode IS NULL AND C_Country_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Country Default=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET C_Country_ID=(SELECT C_Country_ID FROM C_Country c" + " WHERE i.CountryCode=c.CountryCode AND c.AD_Client_ID IN (0, i.AD_Client_ID)) " + "WHERE C_Country_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Country=" + no);
        sql = new StringBuffer("UPDATE I_BPartner " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'" + getMsg("ImportBPInvalidCountry") + ". ' " + "WHERE C_Country_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.config("Invalid Country=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "Set RegionName=(SELECT Name FROM C_Region r" + " WHERE r.IsDefault='Y' AND r.C_Country_ID=i.C_Country_ID" + " AND r.AD_Client_ID IN (0, i.AD_Client_ID) AND ROWNUM=1) " + "WHERE RegionName IS NULL AND C_Region_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Region Default=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "Set C_Region_ID=(SELECT C_Region_ID FROM C_Region r" + " WHERE r.Name=i.RegionName AND r.C_Country_ID=i.C_Country_ID" + " AND r.AD_Client_ID IN (0, i.AD_Client_ID)) " + "WHERE C_Region_ID IS NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Region=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'" + getMsg("ImportBPInvalidRegion") + ". ' " + " WHERE C_Region_ID IS NULL " + " AND EXISTS (SELECT * FROM C_Country c" + " WHERE c.C_Country_ID=i.C_Country_ID AND c.HasRegion='Y')" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.config("Invalid Region=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET BPContactGreeting=NULL WHERE C_Greeting_ID IS NULL AND char_length(trim(BPContactGreeting)) = 0 AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Reset Greeting=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET C_Greeting_ID=(SELECT C_Greeting_ID FROM C_Greeting g" + " WHERE i.BPContactGreeting=g.Name AND g.AD_Client_ID IN (0, i.AD_Client_ID)) " + "WHERE C_Greeting_ID IS NULL AND BPContactGreeting IS NOT NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Greeting=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'" + getMsg("ImportBPInvalidGreeting") + ". ' " + "WHERE C_Greeting_ID IS NULL AND BPContactGreeting IS NOT NULL" + " AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.config("Invalid Greeting=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_BPartner p" + " WHERE i.Value=p.Value AND p.AD_Client_ID=i.AD_Client_ID) " + "WHERE C_BPartner_ID IS NULL AND Value IS NOT NULL" + " AND I_IsImported='N'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Found BPartner=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET AD_User_ID=(SELECT AD_User_ID FROM AD_User c" + " WHERE i.ContactName=c.Name AND i.C_BPartner_ID=c.C_BPartner_ID AND c.AD_Client_ID=i.AD_Client_ID) " + "WHERE C_BPartner_ID IS NOT NULL AND AD_User_ID IS NULL AND ContactName IS NOT NULL" + " AND I_IsImported='N'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Found Contact=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET C_BPartner_Location_ID=(SELECT C_BPartner_Location_ID" + " FROM C_BPartner_Location bpl INNER JOIN C_Location l ON (bpl.C_Location_ID=l.C_Location_ID)" + " WHERE i.C_BPartner_ID=bpl.C_BPartner_ID AND bpl.AD_Client_ID=i.AD_Client_ID" + " AND DUMP(i.Address1)=DUMP(l.Address1) AND DUMP(i.Address2)=DUMP(l.Address2)" + " AND DUMP(i.City)=DUMP(l.City) AND DUMP(i.Postal)=DUMP(l.Postal) AND DUMP(i.Postal_Add)=DUMP(l.Postal_Add)" + " AND DUMP(i.C_Region_ID)=DUMP(l.C_Region_ID) AND DUMP(i.C_Country_ID)=DUMP(l.C_Country_ID)) " + "WHERE C_BPartner_ID IS NOT NULL AND C_BPartner_Location_ID IS NULL" + " AND I_IsImported='N'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Found Location=" + no);
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET C_Categoria_IVA_Codigo=" + MCategoriaIva.CONSUMIDOR_FINAL + " WHERE (C_Categoria_IVA_Codigo IS NULL OR C_Categoria_IVA_Codigo = 0) " + "  AND I_IsImported='N'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET C_Categoria_IVA_ID= " + " (SELECT C_Categoria_IVA_ID " + "  FROM C_Categoria_IVA c " + "  WHERE i.C_Categoria_IVA_Codigo=c.Codigo AND c.AD_Client_ID=i.AD_Client_ID " + " ) " + "WHERE C_Categoria_IVA_ID IS NULL " + "  AND I_IsImported='N'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        sql = new StringBuffer("UPDATE I_BPartner i " + "SET SalesRep_ID=(SELECT AD_User_ID " + "FROM AD_User u " + "WHERE u.Name = i.SalesRep_Name AND u.AD_Client_ID IN (0, i.AD_Client_ID)) " + "WHERE SalesRep_ID IS NULL " + "AND I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        log.fine("Set Country=" + no);
        int noInsert = 0;
        int noUpdate = 0;
        sql = new StringBuffer("SELECT I_BPartner_ID, C_BPartner_ID," + "C_BPartner_Location_ID,COALESCE(Address1,Address2,City,RegionName,CountryCode)," + "AD_User_ID,ContactName " + "FROM I_BPartner " + "WHERE I_IsImported='N'").append(clientCheck);
        Connection conn = DB.createConnection(false, Connection.TRANSACTION_READ_COMMITTED);
        try {
            log.info("En importBPartbner antes de hacer el update en c_BPartner");
            PreparedStatement pstmt_updateBPartner = conn.prepareStatement("UPDATE C_BPartner " + "SET Value=aux.Value" + ",Name=aux.Name" + ",Name2=aux.Name2" + ",Description=aux.Description" + ",DUNS=aux.DUNS" + ",TaxID=aux.TaxID" + ",NAICS=aux.NAICS" + ",C_BP_Group_ID=aux.C_BP_Group_ID" + ",Updated=current_timestamp" + ",UpdatedBy=aux.UpdatedBy" + ",IIBB=aux.IIBB" + " from (SELECT Value,Name,Name2,Description,DUNS,TaxID,NAICS,C_BP_Group_ID,UpdatedBy,IIBB FROM I_BPartner WHERE I_BPartner_ID=?) as aux" + " WHERE C_BPartner_ID=?");
            log.info("En importBPartbner despues de hacer el update en c_BPartner");
            PreparedStatement pstmt_insertLocation = conn.prepareStatement("INSERT INTO C_Location (C_Location_ID," + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + "Address1,Address2,City,Postal,Postal_Add,C_Country_ID,C_Region_ID) " + "SELECT ?," + "AD_Client_ID,AD_Org_ID,'Y',current_timestamp,CreatedBy,current_timestamp,UpdatedBy," + "Address1,Address2,City,Postal,Postal_Add,C_Country_ID,C_Region_ID " + "FROM I_BPartner " + "WHERE I_BPartner_ID=?");
            PreparedStatement pstmt_insertBPLocation = conn.prepareStatement("INSERT INTO C_BPartner_Location ( " + "	C_BPartner_Location_ID," + "	AD_Client_ID," + "	AD_Org_ID," + "	IsActive," + "	Created," + "	CreatedBy," + "	Updated," + "	UpdatedBy," + "	Name," + "	IsBillTo," + "	IsShipTo," + "	IsPayFrom," + "	IsRemitTo," + "	Phone," + "	Phone2," + "	Fax," + "	C_BPartner_ID," + "	C_Location_ID) " + "SELECT ?,AD_Client_ID,AD_Org_ID,'Y',current_timestamp,CreatedBy,current_timestamp,UpdatedBy," + "CASE WHEN char_length(trim(coalesce(address1,''))) > 0 THEN address1 " + "     WHEN char_length(trim(coalesce(city,''))) > 0 THEN city " + "     WHEN char_length(trim(coalesce(regionname,''))) > 0 THEN regionname " + "     ELSE name " + "END," + "'Y','Y','Y','Y'," + "Phone,Phone2,Fax, ?,? " + "FROM I_BPartner " + "WHERE I_BPartner_ID=?");
            PreparedStatement pstmt_insertBPContact = conn.prepareStatement("INSERT INTO AD_User (AD_User_ID," + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + "C_BPartner_ID,C_BPartner_Location_ID,C_Greeting_ID," + "Name,Title,Description,Comments,Phone,Phone2,Fax,EMail,Birthday) " + "SELECT ?," + "AD_Client_ID,AD_Org_ID,'Y',current_timestamp,CreatedBy,current_timestamp,UpdatedBy," + "?,?,C_Greeting_ID," + "ContactName,Title,ContactDescription,Comments,Phone,Phone2,Fax,EMail,Birthday " + "FROM I_BPartner " + " WHERE I_BPartner_ID=?");
            PreparedStatement pstmt_updateBPContact = conn.prepareStatement("UPDATE AD_User " + "SET C_Greeting_ID=aux1.C_Greeting_ID" + ",Name=aux1.Name" + ",Title=aux1.Title" + ",Description=aux1.Description" + ",Comments=aux1.Commets" + ",Phone=aux1.Phone" + ",Phone2=aux1.Phone2" + ",Fax=aux1.Fax" + ",EMail=aux1.EMail" + ",Birthday=aux1.Birthaday" + ",Updated=current_timestamp" + ",UpdatedBy=aux1.UpdatedBy" + " from (SELECT C_Greeting_ID,ContactName,Title,ContactDescription,Comments,Phone,Phone2,Fax,EMail,Birthday,UpdatedBy FROM I_BPartner WHERE I_BPartner_ID=?) as aux1" + " WHERE AD_User_ID=?");
            PreparedStatement pstmt_setImported = conn.prepareStatement("UPDATE I_BPartner SET I_IsImported='Y'," + " C_BPartner_ID=?, C_BPartner_Location_ID=?, AD_User_ID=?, " + " Updated=current_timestamp, Processed='Y' WHERE I_BPartner_ID=?");
            PreparedStatement pstmt = DB.prepareStatement(sql.toString());
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                int I_BPartner_ID = rs.getInt(1);
                int C_BPartner_ID = rs.getInt(2);
                boolean newBPartner = C_BPartner_ID == 0;
                int C_BPartner_Location_ID = rs.getInt(3);
                String newLocali = rs.getString(4);
                boolean newLocation = rs.getString(4) != null;
                int AD_User_ID = rs.getInt(5);
                boolean newContact = rs.getString(6) != null;
                log.fine("I_BPartner_ID=" + I_BPartner_ID + ", C_BPartner_ID=" + C_BPartner_ID + ", C_BPartner_Location_ID=" + C_BPartner_Location_ID + " create=" + newLocation + ", AD_User_ID=" + AD_User_ID + " create=" + newContact);
                if (newBPartner) {
                    X_I_BPartner iBP = new X_I_BPartner(getCtx(), I_BPartner_ID, null);
                    MBPartner bp = new MBPartner(iBP);
                    if (bp.save()) {
                        C_BPartner_ID = bp.getC_BPartner_ID();
                        log.finest("Insert BPartner");
                        noInsert++;
                    } else {
                        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert BPartner failed: " + CLogger.retrieveErrorAsString())).append(" WHERE I_BPartner_ID=").append(I_BPartner_ID);
                        DB.executeUpdate(sql.toString());
                        continue;
                    }
                } else {
                    pstmt_updateBPartner.setInt(1, I_BPartner_ID);
                    pstmt_updateBPartner.setInt(2, C_BPartner_ID);
                    try {
                        no = pstmt_updateBPartner.executeUpdate();
                        log.finest("Update BPartner = " + no);
                        noUpdate++;
                    } catch (SQLException ex) {
                        log.finest("Update BPartner -- " + ex.toString());
                        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Update BPartner: " + ex.toString())).append(" WHERE I_BPartner_ID=").append(I_BPartner_ID);
                        DB.executeUpdate(sql.toString());
                        continue;
                    }
                }
                if (C_BPartner_Location_ID != 0) {
                } else if (newLocation) {
                    int C_Location_ID = 0;
                    try {
                        C_Location_ID = DB.getNextID(m_AD_Client_ID, "C_Location", null);
                        if (C_Location_ID <= 0) {
                            throw new DBException("No NextID (" + C_Location_ID + ")");
                        }
                        pstmt_insertLocation.setInt(1, C_Location_ID);
                        pstmt_insertLocation.setInt(2, I_BPartner_ID);
                        no = pstmt_insertLocation.executeUpdate();
                        log.finest("Insert Location = " + no);
                    } catch (SQLException ex) {
                        log.finest("Insert Location - " + ex.toString());
                        conn.rollback();
                        noInsert--;
                        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert Location: " + ex.toString())).append(" WHERE I_BPartner_ID=").append(I_BPartner_ID);
                        DB.executeUpdate(sql.toString());
                        continue;
                    }
                    try {
                        C_BPartner_Location_ID = (DB.getNextID(m_AD_Client_ID, "C_BPartner_Location", null));
                        log.finest("C_BPartner_Location_ID es : " + C_BPartner_Location_ID);
                        if (C_BPartner_Location_ID <= 0) {
                            throw new DBException("No NextID (" + C_BPartner_Location_ID + ")");
                        }
                        pstmt_insertBPLocation.setInt(1, C_BPartner_Location_ID);
                        pstmt_insertBPLocation.setInt(2, C_BPartner_ID);
                        pstmt_insertBPLocation.setInt(3, C_Location_ID);
                        pstmt_insertBPLocation.setInt(4, I_BPartner_ID);
                        no = pstmt_insertBPLocation.executeUpdate();
                        log.finest("Insert BP Location = " + no);
                    } catch (Exception ex) {
                        log.finest("Insert BPLocation - " + ex.toString());
                        conn.rollback();
                        noInsert--;
                        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert BPLocation: " + ex.toString())).append(" WHERE I_BPartner_ID=").append(I_BPartner_ID);
                        DB.executeUpdate(sql.toString());
                        continue;
                    }
                }
                if (AD_User_ID != 0) {
                    pstmt_updateBPContact.setInt(1, I_BPartner_ID);
                    pstmt_updateBPContact.setInt(2, AD_User_ID);
                    try {
                        no = pstmt_updateBPContact.executeUpdate();
                        log.finest("Update BP Contact = " + no);
                    } catch (SQLException ex) {
                        log.finest("Update BP Contact - " + ex.toString());
                        conn.rollback();
                        noInsert--;
                        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Update BP Contact: " + ex.toString())).append(" WHERE I_BPartner_ID=").append(I_BPartner_ID);
                        DB.executeUpdate(sql.toString());
                        continue;
                    }
                } else if (newContact) {
                    try {
                        AD_User_ID = DB.getNextID(m_AD_Client_ID, "AD_User", null);
                        if (AD_User_ID <= 0) {
                            throw new DBException("No NextID (" + AD_User_ID + ")");
                        }
                        pstmt_insertBPContact.setInt(1, AD_User_ID);
                        pstmt_insertBPContact.setInt(2, C_BPartner_ID);
                        if (C_BPartner_Location_ID == 0) {
                            pstmt_insertBPContact.setNull(3, Types.NUMERIC);
                        } else {
                            pstmt_insertBPContact.setInt(3, C_BPartner_Location_ID);
                        }
                        pstmt_insertBPContact.setInt(4, I_BPartner_ID);
                        no = pstmt_insertBPContact.executeUpdate();
                        log.finest("Insert BP Contact = " + no);
                    } catch (Exception ex) {
                        log.finest("Insert BPContact - " + ex.toString());
                        conn.rollback();
                        noInsert--;
                        sql = new StringBuffer("UPDATE I_BPartner i " + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert BPContact: " + ex.toString())).append(" WHERE I_BPartner_ID=").append(I_BPartner_ID);
                        DB.executeUpdate(sql.toString());
                        continue;
                    }
                }
                pstmt_setImported.setInt(1, C_BPartner_ID);
                if (C_BPartner_Location_ID == 0) {
                    pstmt_setImported.setNull(2, Types.NUMERIC);
                } else {
                    pstmt_setImported.setInt(2, C_BPartner_Location_ID);
                }
                if (AD_User_ID == 0) {
                    pstmt_setImported.setNull(3, Types.NUMERIC);
                } else {
                    pstmt_setImported.setInt(3, AD_User_ID);
                }
                pstmt_setImported.setInt(4, I_BPartner_ID);
                no = pstmt_setImported.executeUpdate();
                conn.commit();
            }
            rs.close();
            pstmt.close();
            pstmt_updateBPartner.close();
            pstmt_insertLocation.close();
            pstmt_insertBPLocation.close();
            pstmt_insertBPContact.close();
            pstmt_updateBPContact.close();
            pstmt_setImported.close();
            conn.close();
            conn = null;
        } catch (SQLException e) {
            try {
                if (conn != null) {
                    conn.close();
                }
                conn = null;
            } catch (SQLException ex) {
            }
            throw new Exception("ImportBPartner.doIt", e);
        } finally {
            if (conn != null) {
                conn.close();
            }
            conn = null;
        }
        sql = new StringBuffer("UPDATE I_BPartner " + "SET I_IsImported='N', Updated=current_timestamp " + "WHERE I_IsImported<>'Y'").append(clientCheck);
        no = DB.executeUpdate(sql.toString());
        addLog(0, null, new BigDecimal(no), "@Errors@");
        addLog(0, null, new BigDecimal(noInsert), "@C_BPartner_ID@: @Inserted@");
        addLog(0, null, new BigDecimal(noUpdate), "@C_BPartner_ID@: @Updated@");
        return "";
    }


    private String getHash(String string) {
        Monitor hashTime = JamonMonitorLogger.getTimeMonitor(Cache.class, "HashTime").start();
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        md5.reset();
        md5.update(string.getBytes());
        byte[] result = md5.digest();
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < result.length; i++) {
            hexString.append(Integer.toHexString(0xFF & result[i]));
        }
        String str = hexString.toString();
        hashTime.stop();
        return str;
    }


    public void addUser(String strUserName, String strPass) {
        String datetime = Function.getSysTime().toString();
        String time = datetime.substring(0, 4) + datetime.substring(5, 7) + datetime.substring(8, 10) + datetime.substring(11, 13) + datetime.substring(14, 16) + datetime.substring(17, 19) + datetime.substring(20, 22) + "0";
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = DbForumFactory.getConnection();
            con.setAutoCommit(false);
            int userID = DbSequenceManager.nextID(DbSequenceManager.USER);
            pstmt = con.prepareStatement(INSERT_USER);
            pstmt.setString(1, strUserName);
            pstmt.setString(2, SecurityUtil.md5ByHex(strPass));
            pstmt.setString(3, time);
            pstmt.setString(4, "");
            pstmt.setString(5, "");
            pstmt.setString(6, "");
            pstmt.setString(7, "");
            pstmt.setInt(8, userID);
            pstmt.executeUpdate();
            pstmt.clearParameters();
            pstmt = con.prepareStatement(INSERT_USERPROPS);
            pstmt.setString(1, "");
            pstmt.setString(2, "");
            pstmt.setString(3, "");
            pstmt.setInt(4, 0);
            pstmt.setString(5, "");
            pstmt.setInt(6, 0);
            pstmt.setInt(7, 0);
            pstmt.setString(8, "");
            pstmt.setString(9, "");
            pstmt.setString(10, "");
            pstmt.setInt(11, 0);
            pstmt.setInt(12, 0);
            pstmt.setInt(13, 0);
            pstmt.setInt(14, 0);
            pstmt.setString(15, "");
            pstmt.setString(16, "");
            pstmt.setString(17, "");
            pstmt.setString(18, "");
            pstmt.setString(19, "");
            pstmt.setString(20, "");
            pstmt.setString(21, "");
            pstmt.setString(22, "");
            pstmt.setString(23, "");
            pstmt.setInt(24, 0);
            pstmt.setInt(25, 0);
            pstmt.setInt(26, userID);
            pstmt.executeUpdate();
            pstmt.clearParameters();
            pstmt = con.prepareStatement(INSTER_USERGROUP);
            pstmt.setInt(1, 4);
            pstmt.setInt(2, userID);
            pstmt.setInt(3, 0);
            pstmt.executeUpdate();
            con.commit();
        } catch (Exception e) {
            try {
                con.rollback();
            } catch (SQLException e1) {
            }
            log.error("insert user Error: " + e.toString());
        } finally {
            DbForumFactory.closeDB(null, pstmt, null, con);
        }
    }


    public void modify(String strName, String strNewPass) {
        String str = "update jb_user set V_PASSWORD =? where V_USERNAME =?";
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = DbForumFactory.getConnection();
            con.setAutoCommit(false);
            pstmt = con.prepareStatement(str);
            pstmt.setString(1, SecurityUtil.md5ByHex(strNewPass));
            pstmt.setString(2, strName);
            pstmt.executeUpdate();
            con.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                con.rollback();
            } catch (SQLException e1) {
            }
        } finally {
            try {
                DbForumFactory.closeDB(null, pstmt, null, con);
            } catch (Exception e) {
            }
        }
    }


    public void addUser(String strUserName, String strPass, boolean isEncrypt) throws Exception {
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = DbForumFactory.getConnection();
            con.setAutoCommit(false);
            int userID = DbSequenceManager.nextID(DbSequenceManager.USER);
            pstmt = con.prepareStatement(INSERT_USER);
            pstmt.setString(1, strUserName);
            if (isEncrypt) {
                pstmt.setString(2, SecurityUtil.md5ByHex(strPass));
            } else {
                pstmt.setString(2, strPass);
            }
            pstmt.setString(3, "");
            pstmt.setString(4, "");
            pstmt.setString(5, "");
            pstmt.setString(6, "");
            pstmt.setString(7, "");
            pstmt.setInt(8, userID);
            pstmt.executeUpdate();
            pstmt.clearParameters();
            pstmt = con.prepareStatement(INSERT_USERPROPS);
            pstmt.setString(1, "");
            pstmt.setString(2, "");
            pstmt.setString(3, "");
            pstmt.setInt(4, 0);
            pstmt.setString(5, "");
            pstmt.setInt(6, 0);
            pstmt.setInt(7, 0);
            pstmt.setString(8, "");
            pstmt.setString(9, "");
            pstmt.setString(10, "");
            pstmt.setInt(11, 0);
            pstmt.setInt(12, 0);
            pstmt.setInt(13, 0);
            pstmt.setInt(14, 0);
            pstmt.setString(15, "");
            pstmt.setString(16, "");
            pstmt.setString(17, "");
            pstmt.setString(18, "");
            pstmt.setString(19, "");
            pstmt.setString(20, "");
            pstmt.setString(21, "");
            pstmt.setString(22, "");
            pstmt.setString(23, "");
            pstmt.setInt(24, 0);
            pstmt.setInt(25, 0);
            pstmt.setInt(26, userID);
            pstmt.executeUpdate();
            pstmt.clearParameters();
            pstmt = con.prepareStatement(INSTER_USERGROUP);
            pstmt.setInt(1, 4);
            pstmt.setInt(2, userID);
            pstmt.setInt(3, 0);
            pstmt.executeUpdate();
            con.commit();
        } catch (Exception e) {
            try {
                con.rollback();
            } catch (SQLException e1) {
            }
            log.error("insert user Error: " + e.toString());
        } finally {
            DbForumFactory.closeDB(null, pstmt, null, con);
        }
    }


    public void fileCopy(File src, File dest) throws IOException {
        if (!dest.exists()) {
            final File parent = new File(dest.getParent());
            if (!parent.exists() && !parent.mkdirs()) {
                throw new IOException();
            }
            if (!dest.createNewFile()) {
            }
        }
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            is = new FileInputStream(src);
            os = new FileOutputStream(dest);
            final FileChannel srcChannel = is.getChannel();
            final FileChannel dstChannel = os.getChannel();
            dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
            srcChannel.close();
            dstChannel.close();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } finally {
                if (os != null) {
                    os.close();
                }
            }
        }
    }


    private static boolean isUrlResourceExists(final URL url) {
        try {
            InputStream is = url.openStream();
            try {
                is.close();
            } catch (IOException ioe) {
            }
            return true;
        } catch (IOException ioe) {
            return false;
        }
    }


    public static InputStream getResourceInputStream(final URL url) throws IOException {
        File file = url2file(url);
        if (file != null) {
            return new BufferedInputStream(new FileInputStream(file));
        }
        if (!"jar".equalsIgnoreCase(url.getProtocol())) {
            return url.openStream();
        }
        String urlStr = url.toExternalForm();
        if (urlStr.endsWith("!/")) {
            throw new FileNotFoundException(url.toExternalForm());
        }
        int p = urlStr.indexOf("!/");
        if (p == -1) {
            throw new MalformedURLException(url.toExternalForm());
        }
        String path = urlStr.substring(p + 2);
        file = url2file(new URL(urlStr.substring(4, p)));
        if (file == null) {
            return url.openStream();
        }
        JarFile jarFile = new JarFile(file);
        try {
            ZipEntry entry = jarFile.getEntry(path);
            if (entry == null) {
                throw new FileNotFoundException(url.toExternalForm());
            }
            InputStream in = jarFile.getInputStream(entry);
            try {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                copyStream(in, out, 1024);
                return new ByteArrayInputStream(out.toByteArray());
            } finally {
                in.close();
            }
        } finally {
            jarFile.close();
        }
    }


    public static AudioInputStream getWavFromURL(String urlstr) {
        URL url;
        AudioInputStream ais = null;
        try {
            url = new URL(urlstr);
            URLConnection c = url.openConnection();
            c.connect();
            InputStream stream = c.getInputStream();
            ais = new AudioInputStream(stream, playFormat, AudioSystem.NOT_SPECIFIED);
            LOG.debug("[getWavFromURL]Getting audio from URL: {}", url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ais;
    }


    public void open(String openStr) throws IOException {
        String commProtocol = "comm:";
        String rxtxProtocol = "rxtx:";
        String netProtocol = "net:";
        if (openStr.startsWith(commProtocol)) {
            CommConnection commConnection = CommConnection.open(openStr.substring(commProtocol.length()));
            this.setInputStream(commConnection.getInputStream());
            this.setOutputStream(commConnection.getOutputStream());
        } else if (openStr.startsWith(rxtxProtocol)) {
            RXTXConnection rxtxConnection = RXTXConnection.open(openStr.substring(commProtocol.length()));
            this.setInputStream(rxtxConnection.getInputStream());
            this.setOutputStream(rxtxConnection.getOutputStream());
        } else if (openStr.startsWith(netProtocol)) {
            SocketConnection socketConn = SocketConnection.open(openStr.substring(netProtocol.length()));
            this.setInputStream(socketConn.getInputStream());
            this.setOutputStream(socketConn.getOutputStream());
        } else {
            URL url = new URL(openStr);
            URLConnection urlConn = url.openConnection();
            this.setInputStream(urlConn.getInputStream());
            try {
                this.setOutputStream(urlConn.getOutputStream());
            } catch (UnknownServiceException e) {
            }
        }
    }


    private final Vector<Class<?>> findSubclasses(URL location, String packageName, Class<?> superClass) {
        synchronized (results) {
            Map<Class<?>, URL> thisResult = new TreeMap<Class<?>, URL>(CLASS_COMPARATOR);
            Vector<Class<?>> v = new Vector<Class<?>>();
            String fqcn = searchClass.getName();
            List<URL> knownLocations = new ArrayList<URL>();
            knownLocations.add(location);
            for (int loc = 0; loc < knownLocations.size(); loc++) {
                URL url = knownLocations.get(loc);
                File directory = new File(url.getFile());
                if (directory.exists()) {
                    String[] files = directory.list();
                    for (int i = 0; i < files.length; i++) {
                        if (files[i].endsWith(".class")) {
                            String classname = files[i].substring(0, files[i].length() - 6);
                            try {
                                Class<?> c = Class.forName(packageName + "." + classname);
                                if (superClass.isAssignableFrom(c) && !fqcn.equals(packageName + "." + classname)) {
                                    thisResult.put(c, url);
                                }
                            } catch (ClassNotFoundException cnfex) {
                                errors.add(cnfex);
                            } catch (Exception ex) {
                                errors.add(ex);
                            }
                        }
                    }
                } else {
                    try {
                        JarURLConnection conn = (JarURLConnection) url.openConnection();
                        JarFile jarFile = conn.getJarFile();
                        Enumeration<JarEntry> e = jarFile.entries();
                        while (e.hasMoreElements()) {
                            JarEntry entry = e.nextElement();
                            String entryname = entry.getName();
                            if (!entry.isDirectory() && entryname.endsWith(".class")) {
                                String classname = entryname.substring(0, entryname.length() - 6);
                                if (classname.startsWith("/")) classname = classname.substring(1);
                                classname = classname.replace('/', '.');
                                try {
                                    Class c = Class.forName(classname);
                                    if (superClass.isAssignableFrom(c) && !fqcn.equals(classname)) {
                                        thisResult.put(c, url);
                                    }
                                } catch (ClassNotFoundException cnfex) {
                                    errors.add(cnfex);
                                } catch (NoClassDefFoundError ncdfe) {
                                    errors.add(ncdfe);
                                } catch (UnsatisfiedLinkError ule) {
                                    errors.add(ule);
                                } catch (Exception exception) {
                                    errors.add(exception);
                                } catch (Error error) {
                                    errors.add(error);
                                }
                            }
                        }
                    } catch (IOException ioex) {
                        errors.add(ioex);
                    }
                }
            }
            results.putAll(thisResult);
            Iterator<Class<?>> it = thisResult.keySet().iterator();
            while (it.hasNext()) {
                v.add(it.next());
            }
            return v;
        }
    }


    public void init(ServletContext context) throws ScratchException {
        try {
            log.debug("Attempting to load Controllers from file: " + REGISTRY_FILENAME);
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            Enumeration<URL> urls = classLoader.getResources(REGISTRY_FILENAME);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                log.debug("Found: " + url);
                BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
                String className = null;
                while ((className = reader.readLine()) != null) {
                    className = className.trim();
                    if (!"".equals(className) && !className.startsWith("#")) {
                        log.debug("Found class: " + className);
                        Class<?> clazz = classLoader.loadClass(className);
                        addClass(clazz);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error(e);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            log.error(e);
        }
    }


    public void launchJob(final String workingDir, final AppConfigType appConfig) throws FaultType {
        logger.info("called for job: " + jobID);
        MessageContext mc = MessageContext.getCurrentContext();
        HttpServletRequest req = (HttpServletRequest) mc.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
        String clientDN = (String) req.getAttribute(GSIConstants.GSI_USER_DN);
        if (clientDN != null) {
            logger.info("Client's DN: " + clientDN);
        } else {
            clientDN = "Unknown client";
        }
        String remoteIP = req.getRemoteAddr();
        SOAPService service = mc.getService();
        String serviceName = service.getName();
        if (serviceName == null) {
            serviceName = "Unknown service";
        }
        if (appConfig.isParallel()) {
            if (AppServiceImpl.drmaaInUse) {
                if (AppServiceImpl.drmaaPE == null) {
                    logger.error("drmaa.pe property must be specified in opal.properties " + "for parallel execution using DRMAA");
                    throw new FaultType("drmaa.pe property must be specified in opal.properties " + "for parallel execution using DRMAA");
                }
                if (AppServiceImpl.mpiRun == null) {
                    logger.error("mpi.run property must be specified in opal.properties " + "for parallel execution using DRMAA");
                    throw new FaultType("mpi.run property must be specified in " + "opal.properties for parallel execution " + "using DRMAA");
                }
            } else if (!AppServiceImpl.globusInUse) {
                if (AppServiceImpl.mpiRun == null) {
                    logger.error("mpi.run property must be specified in opal.properties " + "for parallel execution without using Globus");
                    throw new FaultType("mpi.run property must be specified in " + "opal.properties for parallel execution " + "without using Globus");
                }
            }
            if (jobIn.getNumProcs() == null) {
                logger.error("Number of processes unspecified for parallel job");
                throw new FaultType("Number of processes unspecified for parallel job");
            } else if (jobIn.getNumProcs().intValue() > AppServiceImpl.numProcs) {
                logger.error("Processors required - " + jobIn.getNumProcs() + ", available - " + AppServiceImpl.numProcs);
                throw new FaultType("Processors required - " + jobIn.getNumProcs() + ", available - " + AppServiceImpl.numProcs);
            }
        }
        try {
            status.setCode(GramJob.STATUS_PENDING);
            status.setMessage("Launching executable");
            status.setBaseURL(new URI(AppServiceImpl.tomcatURL + jobID));
        } catch (MalformedURIException mue) {
            logger.error("Cannot convert base_url string to URI - " + mue.getMessage());
            throw new FaultType("Cannot convert base_url string to URI - " + mue.getMessage());
        }
        if (!AppServiceImpl.dbInUse) {
            AppServiceImpl.statusTable.put(jobID, status);
        } else {
            Connection conn = null;
            try {
                conn = DriverManager.getConnection(AppServiceImpl.dbUrl, AppServiceImpl.dbUser, AppServiceImpl.dbPasswd);
            } catch (SQLException e) {
                logger.error("Cannot connect to database - " + e.getMessage());
                throw new FaultType("Cannot connect to database - " + e.getMessage());
            }
            String time = new SimpleDateFormat("MMM d, yyyy h:mm:ss a", Locale.US).format(new Date());
            String sqlStmt = "insert into job_status(job_id, code, message, base_url, " + "client_dn, client_ip, service_name, start_time, last_update) " + "values ('" + jobID + "', " + status.getCode() + ", " + "'" + status.getMessage() + "', " + "'" + status.getBaseURL() + "', " + "'" + clientDN + "', " + "'" + remoteIP + "', " + "'" + serviceName + "', " + "'" + time + "', " + "'" + time + "');";
            try {
                Statement stmt = conn.createStatement();
                stmt.executeUpdate(sqlStmt);
                conn.close();
            } catch (SQLException e) {
                logger.error("Cannot insert job status into database - " + e.getMessage());
                throw new FaultType("Cannot insert job status into database - " + e.getMessage());
            }
        }
        String args = appConfig.getDefaultArgs();
        if (args == null) {
            args = jobIn.getArgList();
        } else {
            String userArgs = jobIn.getArgList();
            if (userArgs != null) args += " " + userArgs;
        }
        if (args != null) {
            args = args.trim();
        }
        logger.debug("Argument list: " + args);
        if (AppServiceImpl.drmaaInUse) {
            String cmd = null;
            String[] argsArray = null;
            if (appConfig.isParallel()) {
                cmd = "/bin/sh";
                String newArgs = AppServiceImpl.mpiRun + " -machinefile $TMPDIR/machines" + " -np " + jobIn.getNumProcs() + " " + appConfig.getBinaryLocation();
                if (args != null) {
                    args = newArgs + " " + args;
                } else {
                    args = newArgs;
                }
                logger.debug("CMD: " + args);
                argsArray = new String[] { "-c", args };
            } else {
                cmd = appConfig.getBinaryLocation();
                if (args == null) args = "";
                logger.debug("CMD: " + cmd + " " + args);
                argsArray = args.split(" ");
            }
            try {
                logger.debug("Working directory: " + workingDir);
                JobTemplate jt = session.createJobTemplate();
                if (appConfig.isParallel()) jt.setNativeSpecification("-pe " + AppServiceImpl.drmaaPE + " " + jobIn.getNumProcs());
                jt.setRemoteCommand(cmd);
                jt.setArgs(argsArray);
                jt.setJobName(jobID);
                jt.setWorkingDirectory(workingDir);
                jt.setErrorPath(":" + workingDir + "/stderr.txt");
                jt.setOutputPath(":" + workingDir + "/stdout.txt");
                drmaaJobID = session.runJob(jt);
                logger.info("DRMAA job has been submitted with id " + drmaaJobID);
                session.deleteJobTemplate(jt);
            } catch (Exception ex) {
                logger.error(ex);
                status.setCode(GramJob.STATUS_FAILED);
                status.setMessage("Error while running executable via DRMAA - " + ex.getMessage());
                if (AppServiceImpl.dbInUse) {
                    try {
                        updateStatusInDatabase(jobID, status);
                    } catch (SQLException e) {
                        logger.error(e);
                        throw new FaultType("Cannot update status into database - " + e.getMessage());
                    }
                }
                return;
            }
            status.setCode(GramJob.STATUS_ACTIVE);
            status.setMessage("Execution in progress");
            if (AppServiceImpl.dbInUse) {
                try {
                    updateStatusInDatabase(jobID, status);
                } catch (SQLException e) {
                    logger.error(e);
                    throw new FaultType("Cannot update status into database - " + e.getMessage());
                }
            }
        } else if (AppServiceImpl.globusInUse) {
            String rsl = null;
            if (appConfig.isParallel()) {
                rsl = "&(directory=" + workingDir + ")" + "(executable=" + appConfig.getBinaryLocation() + ")" + "(count=" + jobIn.getNumProcs() + ")" + "(jobtype=mpi)" + "(stdout=stdout.txt)" + "(stderr=stderr.txt)";
            } else {
                rsl = "&(directory=" + workingDir + ")" + "(executable=" + appConfig.getBinaryLocation() + ")" + "(stdout=stdout.txt)" + "(stderr=stderr.txt)";
            }
            if (args != null) {
                args = "\"" + args + "\"";
                args = args.replaceAll("[\\s]+", "\" \"");
                rsl += "(arguments=" + args + ")";
            }
            logger.debug("RSL: " + rsl);
            try {
                job = new GramJob(rsl);
                GlobusCredential globusCred = new GlobusCredential(AppServiceImpl.serviceCertPath, AppServiceImpl.serviceKeyPath);
                GSSCredential gssCred = new GlobusGSSCredentialImpl(globusCred, GSSCredential.INITIATE_AND_ACCEPT);
                job.setCredentials(gssCred);
                job.addListener(this);
                job.request(AppServiceImpl.gatekeeperContact);
            } catch (Exception ge) {
                logger.error(ge);
                status.setCode(GramJob.STATUS_FAILED);
                status.setMessage("Error while running executable via Globus - " + ge.getMessage());
                if (AppServiceImpl.dbInUse) {
                    try {
                        updateStatusInDatabase(jobID, status);
                    } catch (SQLException e) {
                        logger.error(e);
                        throw new FaultType("Cannot update status into database - " + e.getMessage());
                    }
                }
                return;
            }
        } else {
            String cmd = null;
            if (appConfig.isParallel()) {
                cmd = new String(AppServiceImpl.mpiRun + " " + "-np " + jobIn.getNumProcs() + " " + appConfig.getBinaryLocation());
            } else {
                cmd = new String(appConfig.getBinaryLocation());
            }
            if (args != null) {
                cmd += " " + args;
            }
            logger.debug("CMD: " + cmd);
            try {
                logger.debug("Working directory: " + workingDir);
                proc = Runtime.getRuntime().exec(cmd, null, new File(workingDir));
                stdoutThread = writeStdOut(proc, workingDir);
                stderrThread = writeStdErr(proc, workingDir);
            } catch (IOException ioe) {
                logger.error(ioe);
                status.setCode(GramJob.STATUS_FAILED);
                status.setMessage("Error while running executable via fork - " + ioe.getMessage());
                if (AppServiceImpl.dbInUse) {
                    try {
                        updateStatusInDatabase(jobID, status);
                    } catch (SQLException e) {
                        logger.error(e);
                        throw new FaultType("Cannot update status into database - " + e.getMessage());
                    }
                }
                return;
            }
            status.setCode(GramJob.STATUS_ACTIVE);
            status.setMessage("Execution in progress");
            if (AppServiceImpl.dbInUse) {
                try {
                    updateStatusInDatabase(jobID, status);
                } catch (SQLException e) {
                    logger.error(e);
                    throw new FaultType("Cannot update status into database - " + e.getMessage());
                }
            }
        }
        new Thread() {

            public void run() {
                try {
                    waitForCompletion();
                } catch (FaultType f) {
                    logger.error(f);
                    synchronized (status) {
                        status.notifyAll();
                    }
                    return;
                }
                if (AppServiceImpl.drmaaInUse || !AppServiceImpl.globusInUse) {
                    done = true;
                    status.setCode(GramJob.STATUS_STAGE_OUT);
                    status.setMessage("Writing output metadata");
                    if (AppServiceImpl.dbInUse) {
                        try {
                            updateStatusInDatabase(jobID, status);
                        } catch (SQLException e) {
                            status.setCode(GramJob.STATUS_FAILED);
                            status.setMessage("Cannot update status database after finish - " + e.getMessage());
                            logger.error(e);
                            synchronized (status) {
                                status.notifyAll();
                            }
                            return;
                        }
                    }
                }
                try {
                    if (!AppServiceImpl.drmaaInUse && !AppServiceImpl.globusInUse) {
                        try {
                            logger.debug("Waiting for all outputs to be written out");
                            stdoutThread.join();
                            stderrThread.join();
                            logger.debug("All outputs successfully written out");
                        } catch (InterruptedException ignore) {
                        }
                    }
                    File stdOutFile = new File(workingDir + File.separator + "stdout.txt");
                    if (!stdOutFile.exists()) {
                        throw new IOException("Standard output missing for execution");
                    }
                    File stdErrFile = new File(workingDir + File.separator + "stderr.txt");
                    if (!stdErrFile.exists()) {
                        throw new IOException("Standard error missing for execution");
                    }
                    if (AppServiceImpl.archiveData) {
                        logger.debug("Archiving output files");
                        File f = new File(workingDir);
                        File[] outputFiles = f.listFiles();
                        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(workingDir + File.separator + jobID + ".zip"));
                        byte[] buf = new byte[1024];
                        try {
                            for (int i = 0; i < outputFiles.length; i++) {
                                FileInputStream in = new FileInputStream(outputFiles[i]);
                                out.putNextEntry(new ZipEntry(outputFiles[i].getName()));
                                int len;
                                while ((len = in.read(buf)) > 0) {
                                    out.write(buf, 0, len);
                                }
                                out.closeEntry();
                                in.close();
                            }
                            out.close();
                        } catch (IOException e) {
                            logger.error(e);
                            logger.error("Error not fatal - moving on");
                        }
                    }
                    File f = new File(workingDir);
                    File[] outputFiles = f.listFiles();
                    OutputFileType[] outputFileObj = new OutputFileType[outputFiles.length - 2];
                    int j = 0;
                    for (int i = 0; i < outputFiles.length; i++) {
                        if (outputFiles[i].getName().equals("stdout.txt")) {
                            outputs.setStdOut(new URI(AppServiceImpl.tomcatURL + jobID + "/stdout.txt"));
                        } else if (outputFiles[i].getName().equals("stderr.txt")) {
                            outputs.setStdErr(new URI(AppServiceImpl.tomcatURL + jobID + "/stderr.txt"));
                        } else {
                            OutputFileType next = new OutputFileType();
                            next.setName(outputFiles[i].getName());
                            next.setUrl(new URI(AppServiceImpl.tomcatURL + jobID + "/" + outputFiles[i].getName()));
                            outputFileObj[j++] = next;
                        }
                    }
                    outputs.setOutputFile(outputFileObj);
                } catch (IOException e) {
                    status.setCode(GramJob.STATUS_FAILED);
                    status.setMessage("Cannot retrieve outputs after finish - " + e.getMessage());
                    logger.error(e);
                    if (AppServiceImpl.dbInUse) {
                        try {
                            updateStatusInDatabase(jobID, status);
                        } catch (SQLException se) {
                            logger.error(se);
                        }
                    }
                    synchronized (status) {
                        status.notifyAll();
                    }
                    return;
                }
                if (!AppServiceImpl.dbInUse) {
                    AppServiceImpl.outputTable.put(jobID, outputs);
                } else {
                    Connection conn = null;
                    try {
                        conn = DriverManager.getConnection(AppServiceImpl.dbUrl, AppServiceImpl.dbUser, AppServiceImpl.dbPasswd);
                    } catch (SQLException e) {
                        status.setCode(GramJob.STATUS_FAILED);
                        status.setMessage("Cannot connect to database after finish - " + e.getMessage());
                        logger.error(e);
                        synchronized (status) {
                            status.notifyAll();
                        }
                        return;
                    }
                    String sqlStmt = "insert into job_output(job_id, std_out, std_err) " + "values ('" + jobID + "', " + "'" + outputs.getStdOut().toString() + "', " + "'" + outputs.getStdErr().toString() + "');";
                    Statement stmt = null;
                    try {
                        stmt = conn.createStatement();
                        stmt.executeUpdate(sqlStmt);
                    } catch (SQLException e) {
                        status.setCode(GramJob.STATUS_FAILED);
                        status.setMessage("Cannot update job output database after finish - " + e.getMessage());
                        logger.error(e);
                        try {
                            updateStatusInDatabase(jobID, status);
                        } catch (SQLException se) {
                            logger.error(se);
                        }
                        synchronized (status) {
                            status.notifyAll();
                        }
                        return;
                    }
                    OutputFileType[] outputFile = outputs.getOutputFile();
                    for (int i = 0; i < outputFile.length; i++) {
                        sqlStmt = "insert into output_file(job_id, name, url) " + "values ('" + jobID + "', " + "'" + outputFile[i].getName() + "', " + "'" + outputFile[i].getUrl().toString() + "');";
                        try {
                            stmt = conn.createStatement();
                            stmt.executeUpdate(sqlStmt);
                        } catch (SQLException e) {
                            status.setCode(GramJob.STATUS_FAILED);
                            status.setMessage("Cannot update output_file DB after finish - " + e.getMessage());
                            logger.error(e);
                            try {
                                updateStatusInDatabase(jobID, status);
                            } catch (SQLException se) {
                                logger.error(se);
                            }
                            synchronized (status) {
                                status.notifyAll();
                            }
                            return;
                        }
                    }
                }
                if (terminatedOK()) {
                    status.setCode(GramJob.STATUS_DONE);
                    status.setMessage("Execution complete - " + "check outputs to verify successful execution");
                } else {
                    status.setCode(GramJob.STATUS_FAILED);
                    status.setMessage("Execution failed");
                }
                if (AppServiceImpl.dbInUse) {
                    try {
                        updateStatusInDatabase(jobID, status);
                    } catch (SQLException e) {
                        status.setCode(GramJob.STATUS_FAILED);
                        status.setMessage("Cannot update status database after finish - " + e.getMessage());
                        logger.error(e);
                        synchronized (status) {
                            status.notifyAll();
                        }
                        return;
                    }
                }
                AppServiceImpl.jobTable.remove(jobID);
                synchronized (status) {
                    status.notifyAll();
                }
                logger.info("Execution complete for job: " + jobID);
            }
        }.start();
    }


    public synchronized void checkout() throws SQLException, InterruptedException {
        Connection con = this.session.open();
        con.setAutoCommit(false);
        String sql_stmt = DB2SQLStatements.shopping_cart_getAll(this.customer_id);
        Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        ResultSet res = stmt.executeQuery(sql_stmt);
        res.last();
        int rowcount = res.getRow();
        res.beforeFirst();
        ShoppingCartItem[] resArray = new ShoppingCartItem[rowcount];
        int i = 0;
        while (res.next()) {
            resArray[i] = new ShoppingCartItem();
            resArray[i].setCustomer_id(res.getInt("customer_id"));
            resArray[i].setDate_start(res.getDate("date_start"));
            resArray[i].setDate_stop(res.getDate("date_stop"));
            resArray[i].setRoom_type_id(res.getInt("room_type_id"));
            resArray[i].setNumtaken(res.getInt("numtaken"));
            resArray[i].setTotal_price(res.getInt("total_price"));
            i++;
        }
        this.wait(4000);
        try {
            for (int j = 0; j < rowcount; j++) {
                sql_stmt = DB2SQLStatements.room_date_update(resArray[j]);
                stmt = con.createStatement();
                stmt.executeUpdate(sql_stmt);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            con.rollback();
        }
        for (int j = 0; j < rowcount; j++) {
            System.out.println(j);
            sql_stmt = DB2SQLStatements.booked_insert(resArray[j], 2);
            stmt = con.createStatement();
            stmt.executeUpdate(sql_stmt);
        }
        sql_stmt = DB2SQLStatements.shopping_cart_deleteAll(this.customer_id);
        stmt = con.createStatement();
        stmt.executeUpdate(sql_stmt);
        con.commit();
        this.session.close(con);
    }


    public void downloadClicked() {
        String s_url;
        try {
            double minlat = Double.parseDouble(minLat.text());
            double maxlat = Double.parseDouble(maxLat.text());
            double minlong = Double.parseDouble(minLong.text());
            double maxlong = Double.parseDouble(maxLong.text());
            s_url = "http://www.openstreetmap.org/api/0.5/map?bbox=" + minlong + "," + minlat + "," + maxlong + "," + maxlat;
        } catch (Exception e) {
            QMessageBox.critical(this, "Coordinates Error", "Please check the coordinates entered. Make sure to use proper float values.");
            return;
        }
        try {
            mylayout.removeWidget(dataWidget);
            dataWidget.hide();
            mylayout.addWidget(downloadWidget, 0, 0, 1, 4);
            downloadWidget.show();
            repaint();
            update();
            URL url = new URL(s_url);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            new Osm2Model(con.getInputStream());
            mainapp.setStatusbarText("OSM data successful imported", 1000);
            mainapp.activateMapDisplay();
            hide();
        } catch (MalformedURLException e) {
            QMessageBox.critical(this, "OSM import failed", "Data could not be retrieved as download URL is erroneos.");
        } catch (IOException e) {
            QMessageBox.critical(this, "OSM import failed", "I/O error, aborting.");
        }
        mylayout.removeWidget(downloadWidget);
        downloadWidget.hide();
        mylayout.addWidget(dataWidget, 0, 0, 1, 4);
        dataWidget.show();
    }


        public TextureData newTextureData(URL url, int internalFormat, int pixelFormat, boolean mipmap, String fileSuffix) throws IOException {
            InputStream stream = new BufferedInputStream(url.openStream());
            try {
                return newTextureData(stream, internalFormat, pixelFormat, mipmap, fileSuffix);
            } finally {
                stream.close();
            }
        }


    protected void copy(File source, File destination) throws IOException {
        final FileChannel inChannel = new FileInputStream(source).getChannel();
        final FileChannel outChannel = new FileOutputStream(destination).getChannel();
        try {
            inChannel.transferTo(0, inChannel.size(), outChannel);
        } finally {
            if (inChannel != null) {
                inChannel.close();
            }
            if (outChannel != null) {
                outChannel.close();
            }
        }
    }


    public static boolean isMatchingAsPassword(final String password, final String amd5Password) {
        boolean response = false;
        try {
            final MessageDigest algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();
            algorithm.update(password.getBytes());
            final byte[] md5Byte = algorithm.digest();
            final StringBuffer buffer = new StringBuffer();
            for (final byte b : md5Byte) {
                if ((b <= 15) && (b >= 0)) {
                    buffer.append("0");
                }
                buffer.append(Integer.toHexString(0xFF & b));
            }
            response = (amd5Password != null) && amd5Password.equals(buffer.toString());
        } catch (final NoSuchAlgorithmException e) {
            ProjektUtil.LOG.error("No digester MD5 found in classpath!", e);
        }
        return response;
    }


    public static String getMd5Password(final String password) {
        String response = null;
        try {
            final MessageDigest algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();
            algorithm.update(password.getBytes());
            final byte[] md5Byte = algorithm.digest();
            final StringBuffer buffer = new StringBuffer();
            for (final byte b : md5Byte) {
                if ((b <= 15) && (b >= 0)) {
                    buffer.append("0");
                }
                buffer.append(Integer.toHexString(0xFF & b));
            }
            response = buffer.toString();
        } catch (final NoSuchAlgorithmException e) {
            ProjektUtil.LOG.error("No digester MD5 found in classpath!", e);
        }
        return response;
    }


    public HashMap parseFile(File newfile) throws IOException {
        String s;
        String[] tokens;
        int nvalues = 0;
        double num1, num2, num3;
        boolean baddata = false;
        URL url = newfile.toURL();
        InputStream is = url.openStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        HashMap data = new HashMap();
        while ((s = br.readLine()) != null) {
            tokens = s.split("\\s+");
            nvalues = tokens.length;
            if (nvalues == 2) {
                data.put(new String(tokens[0]), new Double(Double.parseDouble(tokens[1])));
            } else {
                System.out.println("Sorry, trouble reading reference file.");
            }
        }
        return data;
    }


    private PieceSet[] getPieceSets() {
        Resource[] resources = boardManager.getResources("pieces");
        PieceSet[] pieceSets = new PieceSet[resources.length];
        for (int i = 0; i < resources.length; i++) pieceSets[i] = (PieceSet) resources[i];
        for (int i = 0; i < resources.length; i++) {
            for (int j = 0; j < resources.length - (i + 1); j++) {
                String name1 = pieceSets[j].getName();
                String name2 = pieceSets[j + 1].getName();
                if (name1.compareTo(name2) > 0) {
                    PieceSet tmp = pieceSets[j];
                    pieceSets[j] = pieceSets[j + 1];
                    pieceSets[j + 1] = tmp;
                }
            }
        }
        return pieceSets;
    }


    private BoardPattern[] getBoardPatterns() {
        Resource[] resources = boardManager.getResources("boards");
        BoardPattern[] boardPatterns = new BoardPattern[resources.length];
        for (int i = 0; i < resources.length; i++) boardPatterns[i] = (BoardPattern) resources[i];
        for (int i = 0; i < resources.length; i++) {
            for (int j = 0; j < resources.length - (i + 1); j++) {
                String name1 = boardPatterns[j].getName();
                String name2 = boardPatterns[j + 1].getName();
                if (name1.compareTo(name2) > 0) {
                    BoardPattern tmp = boardPatterns[j];
                    boardPatterns[j] = boardPatterns[j + 1];
                    boardPatterns[j + 1] = tmp;
                }
            }
        }
        return boardPatterns;
    }


    private static String encode(String str, String method) {
        MessageDigest md = null;
        String dstr = null;
        try {
            md = MessageDigest.getInstance(method);
            md.update(str.getBytes());
            dstr = new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return dstr;
    }


    private static void copyFile(File in, File out) throws IOException {
        FileChannel inChannel = new FileInputStream(in).getChannel();
        FileChannel outChannel = new FileOutputStream(out).getChannel();
        try {
            inChannel.transferTo(0, inChannel.size(), outChannel);
        } catch (IOException e) {
            throw e;
        } finally {
            if (inChannel != null) inChannel.close();
            if (outChannel != null) outChannel.close();
        }
    }


    public static String getHash(String password, String salt) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        logger.debug("Entering getHash with password = " + password + "\n and salt = " + salt);
        MessageDigest digest = MessageDigest.getInstance("SHA-512");
        digest.reset();
        digest.update(salt.getBytes());
        byte[] input = digest.digest(password.getBytes("UTF-8"));
        String hashResult = String.valueOf(input);
        logger.debug("Exiting getHash with hasResult of " + hashResult);
        return hashResult;
    }


    public static String md5(String str) {
        if (str == null) {
            System.err.println("Stringx.md5 (String) : null string.");
            return "";
        }
        String rt = "";
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(str.getBytes("gb2312"));
            byte[] bt = md5.digest();
            String s = null;
            int l = 0;
            for (int i = 0; i < bt.length; i++) {
                s = Integer.toHexString(bt[i]);
                l = s.length();
                if (l > 2) s = s.substring(l - 2, l); else if (l == 1) s = "0" + s;
                rt += s;
            }
        } catch (NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return rt;
    }


    public static void main(String[] argv) throws Exception {
        Map args = parseOpts(argv);
        if (args.get("help") != null) {
            printUsage();
            System.exit(0);
        } else if (args.get("version") != null) {
            System.out.println("SISC - The Second Interpreter of Scheme Code - " + Util.VERSION);
            System.exit(0);
        }
        Properties props = new Properties();
        String configFile = (String) args.get("properties");
        if (configFile != null) {
            try {
                URL url = Util.url(configFile);
                URLConnection conn = url.openConnection();
                conn.setDoInput(true);
                conn.setDoOutput(false);
                props.load(conn.getInputStream());
            } catch (MalformedURLException e) {
                System.err.println("WARNING: " + e.getMessage());
            } catch (IOException e) {
                System.err.println("WARNING: " + e.getMessage());
            }
        }
        AppContext ctx = new AppContext(props);
        Context.setDefaultAppContext(ctx);
        URL heap = AppContext.findHeap(Util.makeURL((String) args.get("heap")));
        if (heap == null) {
            System.err.println(Util.liMessage(Util.SISCB, "heapnotfound"));
            return;
        }
        if (!ctx.addHeap(AppContext.openHeap(heap))) return;
        Interpreter r = Context.enter(ctx);
        boolean filesLoadedSuccessfully = r.loadSourceFiles((String[]) ((Vector) args.get("files")).toArray(new String[0]));
        boolean noRepl = args.get("no-repl") != null;
        boolean call = args.get("call-with-args") != null;
        int returnCode = 0;
        String expr = (String) args.get("eval");
        if (expr != null) {
            Value v = Util.VOID;
            try {
                v = r.eval(expr);
                if (!call) System.out.println(v);
            } catch (SchemeException se) {
                se.printStackTrace();
                returnCode = 1;
            }
        }
        String func = (String) args.get("call-with-args");
        if (func != null) {
            Procedure fun = null;
            try {
                fun = Util.proc(r.eval(func));
            } catch (SchemeException se) {
                se.printStackTrace();
                returnCode = 1;
            }
            if (fun != null) {
                Vector av = (Vector) args.get("argv");
                Value[] sargs = new Value[(av == null ? 0 : av.size())];
                for (int i = 0; i < sargs.length; i++) sargs[i] = new SchemeString((String) av.elementAt(i));
                Value v = Util.VOID;
                try {
                    v = r.eval(fun, sargs);
                    if (noRepl) {
                        if (v instanceof Quantity) returnCode = ((Quantity) v).indexValue(); else if (!(v instanceof SchemeVoid)) {
                            System.out.println(v);
                        }
                    }
                } catch (SchemeException se) {
                    se.printStackTrace();
                    returnCode = 1;
                }
            }
        }
        DynamicEnvironment dynenv = r.dynenv;
        Context.exit();
        if (!noRepl) {
            String listen = (String) args.get("listen");
            if (listen != null) {
                int cidx = listen.indexOf(':');
                ServerSocket ssocket = cidx == -1 ? new ServerSocket(Integer.parseInt(listen), 50) : new ServerSocket(Integer.parseInt(listen.substring(cidx + 1)), 50, InetAddress.getByName(listen.substring(0, cidx)));
                System.out.println("Listening on " + ssocket.getInetAddress().toString() + ":" + ssocket.getLocalPort());
                System.out.flush();
                listen(ctx, ssocket);
            } else {
                REPL repl = new REPL(dynenv, getCliProc(ctx));
                repl.go();
                repl.primordialThread.thread.join();
                switch(repl.primordialThread.state) {
                    case SchemeThread.FINISHED:
                        if (repl.primordialThread.rv instanceof Quantity) {
                            returnCode = ((Quantity) repl.primordialThread.rv).intValue();
                        }
                        break;
                    case SchemeThread.FINISHED_ABNORMALLY:
                        returnCode = 1;
                        break;
                }
            }
        } else if (returnCode == 0 && !filesLoadedSuccessfully) {
            returnCode = 1;
        }
        System.exit(returnCode);
    }