2012-07-09 16 views
12

Tôi đang sử dụng các geotools để trích xuất dữ liệu từ shapefile và lưu chúng vào mysql. ứng dụng của tôi làm việc tất cả các thời gian nhưng tôi nhận được khóa này cũng thường mà tôi không thể hiểu tại sao, vì nó vẫn hoạt độnggeotools SEVERE: Tủ khóa sau vẫn có khóa đọc trên hồ sơ

[[email protected] filespool]# /usr/bin/java -jar /opt/mcmap/library/Application/geotools/mcgeotools.jar -t publisher -i 1/194/Namibia_SCLB12.shp -rid 12 -s 
app get cmd option cast to int: 12 
app passing region id to runconvert: 12 
runconvert rid passed: 12 
Jul 9, 2012 4:23:48 PM org.geotools.data.db2.DB2DataStoreFactory isAvailable 
INFO: DB2 driver found: true 
Database connection acquired 
Coordinates length: 5390 
Coordinates length: 5358 
Coordinates length: 9932 
Jul 9, 2012 4:28:14 PM org.geotools.data.shapefile.ShpFiles logCurrentLockers 
SEVERE: The following locker still has a lock� read on file:/opt/mcmap/public/filespool/1/194/Namibia_SCLB12.prj by org.geotools.data.shapefile.prj.PrjFileReader 
it was created with the following stack trace 
org.geotools.data.shapefile.ShpFilesLocker$Trace: Locking file:/opt/mcmap/public/filespool/1/194/Namibia_SCLB12.prj for read by org.geotools.data.shapefile.prj.PrjFileReader in thread main 
    at org.geotools.data.shapefile.ShpFilesLocker.setTraceException(ShpFilesLocker.java:72) 
    at org.geotools.data.shapefile.ShpFilesLocker.<init>(ShpFilesLocker.java:36) 
    at org.geotools.data.shapefile.ShpFiles.acquireRead(ShpFiles.java:365) 
    at org.geotools.data.shapefile.ShpFiles.getReadChannel(ShpFiles.java:813) 
    at org.geotools.data.shapefile.prj.PrjFileReader.<init>(PrjFileReader.java:66) 
    at com.domain.mcgeotools.convert.Converter.getCoordinateSystem(Converter.java:521) 
    at com.domain.mcgeotools.convert.Converter.runConvert(Converter.java:106) 
    at com.domain.mcgeotools.App.main(App.java:158) 
Coordinates length: 5741 
Coordinates length: 5374 
Coordinates length: 4193 
Coordinates length: 14161 
Coordinates length: 5375 
Coordinates length: 4212 

dưới đây là mã ứng dụng của tôi

package com.domain.mcgeotools.convert; 
import com.vividsolutions.jts.geom.Coordinate; 
import com.vividsolutions.jts.geom.Geometry; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.File; 
import java.net.ConnectException; 
import java.net.MalformedURLException; 
import java.util.Properties; 
import java.util.Collection; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import java.sql.*; 
import org.geotools.data.DataStore; 
import org.geotools.data.DataStoreFinder; 
import org.geotools.data.FeatureSource; 
import org.geotools.data.shapefile.*; 
import org.geotools.data.shapefile.prj.PrjFileReader; 
import org.geotools.feature.FeatureCollection; 
import org.geotools.feature.FeatureIterator; 
import org.geotools.feature.simple.SimpleFeatureImpl; 
import org.opengis.feature.Property; 
import org.opengis.referencing.crs.CoordinateReferenceSystem; 

public class Converter { 

    protected String filePath = null; 
    private Properties configFile = null; 
    private String[] acceptedCoordinateSytems = { 
     "Lat Long for MAPINFO type 0 Datum", 
     "GCS_WGS_1984" 
    }; 
    private HashMap sqlStatements = new HashMap(); 
    private int sqlCounter = 0; 


    public Converter() throws IOException { 

     /** 
     * We load the configuration details from the properties file and use the config. The config property 
     * item stores things such as database connection details etc. 
     */ 
     this.configFile = new Properties(); 
     this.configFile.load(this.getClass().getClassLoader().getResourceAsStream("mcgeotools-config.properties")); 
    } 

    protected void setFilePath(String filePath) { 
     this.filePath = filePath; 
    } 

    protected String getFilePath() { 
     return this.filePath; 
    } 

    /** 
    * Converts the passed shape files and place the data into the RDBMS 
    * 
    * @param filePath 
    * @param verbose 
    * @param shrink 
    * @return 
    * @throws Exception 
    */ 
    public int runConvert(String filePath, int regionId, boolean verbose, boolean shrink, String type) throws Exception { 
     System.out.println("runconvert rid passed: " + regionId); 
     ShapeFile shapeFile = new ShapeFile(); 
     if (!shapeFile.isShapeFile(filePath)) { 
      System.out.println(filePath); 
      throw new Exception("Not a shape file"); 
     } 
     //we get the coordinate type from the shape file 
     String coordinateSystem = null; 
     try { 
      coordinateSystem = this.getCoordinateSystem(filePath); 
      if (verbose) { 
       //Print to console. 
       System.out.println("Coordinate System: " + coordinateSystem + " for " + filePath); 
      } 

     } catch (Exception cse) { 
      Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, cse); 
     } 

     boolean acceptedSystem = false; 

     for (int i = 0; i < this.acceptedCoordinateSytems.length; i++) { 
      if (this.acceptedCoordinateSytems[i].equalsIgnoreCase(coordinateSystem)) { 
       acceptedSystem = true; 
      } 
     } 

     if (!acceptedSystem) { 
      throw new Exception("Not an excepted Coordinate System."); 
     } 

     //we now load the shapefile into the application 
     File file = new File(filePath); 

     if (file == null) { 
      throw new Exception("Failed to open " + filePath); 
     } 

     Map connect = new HashMap(); 
     connect.put("url", file.toURI().toURL()); 

     DataStore dataStore = DataStoreFinder.getDataStore(connect); 
     String[] typeNames = dataStore.getTypeNames(); 
     String typeName = typeNames[0]; 

     FeatureSource featureSource = dataStore.getFeatureSource(typeName); 
     FeatureCollection collection = featureSource.getFeatures(); 
     FeatureIterator iterator = collection.features(); 

     //database connection 
     Connection dbConn = null; 

     int surveyDbId = 0; 

     String localhostname = java.net.InetAddress.getLocalHost().getHostName(); 

     try { 

      String dbUser = "", dbPwd = "", dbUrl = ""; 

      dbUser = this.configFile.getProperty("DB_USER"); 
      dbPwd = this.configFile.getProperty("DB_PASSWORD"); 
      dbUrl = "jdbc:" + this.configFile.getProperty("DB_CONNSTR"); 
      dbUrl = "jdbc:mysql://"+ localhostname +"/mcdatabase"; 

      // If publishing overite connection strings 
      if(type.equals("publish")){ 
       dbUser = this.configFile.getProperty("DB_PB_USER"); 
       dbPwd = this.configFile.getProperty("DB_PB_PASSWORD"); 
       dbUrl = "jdbc:" + this.configFile.getProperty("DB_PB_CONNSTR"); 
      } 

      Class.forName("com.mysql.jdbc.Driver").newInstance(); 
      dbConn = DriverManager.getConnection(dbUrl, dbUser, dbPwd); 

      System.out.println("Database connection acquired"); 

      //switch off auto commits so that we run this as one transaction. 
      dbConn.setAutoCommit(false); 

      this.sqlStatements.put(this.sqlCounter, "START TRANSACTION"); 
      this.sqlCounter++; 

      PreparedStatement surveyStmt = null; 
      ResultSet rs = null; 

      if(type.equals("convert")){ 

       //insert data in to the survey table and get the last row ID. 
       surveyStmt = dbConn.prepareStatement("INSERT INTO surveys (name, guid, date_added, region_id, shrink) VALUES(?, md5(now()), now(), ?, ?)"); 
       surveyStmt.setString(1, typeName.replaceAll("%20", " ")); 
       surveyStmt.setInt(2, regionId); 
       surveyStmt.setBoolean(3, shrink); 
       surveyStmt.executeUpdate(); 
       rs = surveyStmt.getGeneratedKeys(); 
       rs.first(); 
       surveyDbId = rs.getInt(1); 

       this.sqlStatements.put(this.sqlCounter, "INSERT INTO surveys (name, guid, date_added, region_id, shrink) VALUES('"+ typeName.replaceAll("%20", " ") +"', md5(now()), now(), "+ regionId +", "+ shrink +")"); 


      }else if(type.equals("publish")){ 
       //insert data in to the survey table and get the last row ID. 
       surveyStmt = dbConn.prepareStatement("INSERT INTO surveys (name, guid, published, date_added, region_id, shrink) VALUES(?, md5(now()), 1, now(), ?, ?)"); 
       surveyStmt.setString(1, typeName.replaceAll("%20", " ")); 
       surveyStmt.setInt(2, regionId); 
       surveyStmt.setBoolean(3, shrink); 
       surveyStmt.executeUpdate(); 
       rs = surveyStmt.getGeneratedKeys(); 
       rs.first(); 
       surveyDbId = rs.getInt(1); 

       this.sqlStatements.put(this.sqlCounter, "INSERT INTO surveys (name, guid, published, date_added, region_id, shrink) VALUES('"+ typeName.replaceAll("%20", " ") +"', md5(now()), 1, now(), "+ regionId +", "+ shrink +")"); 

      } 
      this.sqlCounter++; 

      rs.close(); 
      surveyStmt.close(); 

      //Total lat/long values to work center point. 
      double totalLat = 0.0; 
      double totalLong = 0.0; 
      int totalLongLats = 0; 


      while (iterator.hasNext()) { 

       SimpleFeatureImpl feature = (SimpleFeatureImpl) iterator.next(); 
       Geometry sourceGeometry = (Geometry) feature.getDefaultGeometry(); 

       //we now need to enter a link between the survey and the line data. 
       PreparedStatement lineStmt = null; 
       String lineStmtSQL = "INSERT INTO `lines` (guid, date_added, survey_id) VALUES (md5(now()), now(), ?)"; 
       lineStmt = dbConn.prepareCall(lineStmtSQL); 
       lineStmt.setInt(1, surveyDbId); 
       lineStmt.executeUpdate(); 
       ResultSet lineRS = lineStmt.getGeneratedKeys(); 
       lineRS.first(); 
       int lineDbId = lineRS.getInt(1); 

       this.sqlStatements.put(this.sqlCounter, "INSERT INTO `lines` (guid, date_added, survey_id) VALUES (md5(now()), now(), " + 
       surveyDbId +")"); 
       this.sqlCounter++; 


       lineRS.close(); 
       lineStmt.close(); 

       //we now look for the properties of the line that we are about to process. 
       Collection<Property> coll = feature.getProperties(); 
       Iterator colIterator = coll.iterator(); 

       //we now look at inserting the line properties into the database. 
       PreparedStatement linePropStmt = null; 
       String linePropSQL = "INSERT INTO line_properties(`key`, `value`, `line_id`) VALUES(?, ?, ?)"; 
       linePropStmt = dbConn.prepareStatement(linePropSQL); 

       while (colIterator.hasNext()) { 

        Property geoProp = (Property) colIterator.next(); 
        if (verbose) { 
         System.out.println("prop name: " + geoProp.getName() + " Value: " + geoProp.getValue()); 
        } 

        if (geoProp.getValue() != null && !geoProp.getName().toString().equals("the_geom")) { 
         //we then prepare the statment and execute for each property. 
         linePropStmt.setString(1, geoProp.getName().toString()); 
         linePropStmt.setString(2, geoProp.getValue().toString()); 
         linePropStmt.setInt(3, lineDbId); 

         linePropStmt.executeUpdate(); 

         //add to sql command hashmap 
         this.sqlStatements.put(this.sqlCounter, "INSERT INTO line_properties(`key`, `value`, `line_id`) VALUES('" + 
         geoProp.getName().toString()+"', '"+ 
         geoProp.getValue().toString()+"', "+lineDbId+")"); 
         this.sqlCounter++; 
        } 

       } 

       //close the prepared statement now that we've finished with it. 
       linePropStmt.close(); 


       //finally we populate the line coordinates into the database. 
       Coordinate[] coordinates = sourceGeometry.getCoordinates(); 
       String lineName = feature.getID(); 
       if (verbose) { 
        System.out.println(lineName); 
       } 

       PreparedStatement coordStmt = null; 
       String coordSQL = "INSERT INTO coordinates(`x`, `y`, line_id, sequence) VALUES(?, ?, ?, ?)"; 
       coordStmt = dbConn.prepareStatement(coordSQL); 

       PreparedStatement lineStringStmt = null; 
       String longLatSQL = "UPDATE `lines` SET longlat_string = ? WHERE line_id = ?"; 
       lineStringStmt = dbConn.prepareStatement(longLatSQL); 

       /** 
       * Used to build a full long lat string for fast lookups 
       * when being used in KML/Google Maps 
       */ 
       String longLatString = ""; 
       boolean first = true; 
       int shotCount = 0; 

       System.out.println("Coordinates length: "+ coordinates.length); 

       for (int i = 0; i < coordinates.length; i++) { 

        if (verbose) { 
         System.out.println("x: " + coordinates[i].x + " - Y: " + coordinates[i].y); 
        } 

        //add to the long lat counter to find center point 
        totalLat += coordinates[i].x; 
        totalLong += coordinates[i].y; 
        totalLongLats++; 

        coordStmt.setString(1, Double.toString(coordinates[i].x)); 
        coordStmt.setString(2, Double.toString(coordinates[i].y)); 
        coordStmt.setInt(3, lineDbId); 
        coordStmt.setInt(4, i); 

        coordStmt.executeUpdate(); 

        this.sqlStatements.put(this.sqlCounter, "INSERT INTO coordinates(`x`, `y`, line_id, sequence) VALUES('"+ 
        Double.toString(coordinates[i].x) +"', '"+ 
        Double.toString(coordinates[i].y) +"', "+lineDbId+", "+i+")"); 
        this.sqlCounter++; 


        //now we build/update a string for the full coordinates. 
        if (first) { 

         longLatString = Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 

         first = false; 

        } else { 

         // Not implemented function fully, to strip long lats to start and end points only 
         if(shrink){ 

          if(i == (coordinates.length -1)){ 
           longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
          } 

         }else{ 
          /* // testing this if 
          if(coordinates.length < 10 && shotCount == 2){ 
           longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
           shotCount = 0; 

          }else */ 
           //if(coordinates.length >= 10 && coordinates.length < 30 && shotCount == 4){ 
           if(coordinates.length < 30 && shotCount == 4){ 
            longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
            shotCount = 0; 

           }else if(coordinates.length >= 30 && coordinates.length < 100 && shotCount == 9){ 
            longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
            shotCount = 0; 

           }else if(coordinates.length >= 100 && coordinates.length < 1000 && shotCount == 49){ 
            longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
            shotCount = 0; 

           }else if(coordinates.length >= 1000 && coordinates.length < 10000 && shotCount == 99){ 
            longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
            shotCount = 0; 

           }else if(coordinates.length >= 10000 && shotCount == 199){ 
            longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
            shotCount = 0; 
           } 

           // Make sure to get last co-ordinate of line 
           if(i == (coordinates.length-1)){ // -1 since coutn starts from zero 
           longLatString += ",0 " + Double.toString(coordinates[i].x) + "," + Double.toString(coordinates[i].y); 
           System.out.println("Last coordinate stored: " + longLatString); 
           shotCount = 0; 
          } 
         } 

        } 

        shotCount ++; 
       } 

       /** 
       * Update the line table to include the precreated line string. 
       */ 
       lineStringStmt.setString(1, longLatString); 
       lineStringStmt.setInt(2, lineDbId); 
       lineStringStmt.executeUpdate(); 

       this.sqlStatements.put(this.sqlCounter, "UPDATE `lines` SET longlat_string = '"+longLatString+"' WHERE line_id = " + lineDbId); 
       this.sqlCounter++; 

       lineStringStmt.close(); 
       coordStmt.close(); 


      } 

      //finally we update the center point 
      PreparedStatement centerPointStmt = null; 
      String centerPointSQL = "UPDATE `surveys` SET center_point = ? WHERE survey_id = ?"; 
      centerPointStmt = dbConn.prepareStatement(centerPointSQL); 

      double centerLat = totalLat/totalLongLats; 
      double centerLong = totalLong/totalLongLats; 

      String centerPoint = Double.toString(centerLat) + ", " + Double.toString(centerLong); 

      centerPointStmt.setString(1, centerPoint); 
      centerPointStmt.setInt(2, surveyDbId); 
      centerPointStmt.executeUpdate(); 
      centerPointStmt.close(); 

      this.sqlStatements.put(this.sqlCounter, "UPDATE `surveys` SET center_point = '"+centerPoint+"' WHERE survey_id = "+surveyDbId); 
      this.sqlCounter++; 

      //we now commit the transaction 
      dbConn.commit(); 
      //now we can close the database connection. 
      dbConn.close(); 

      this.sqlStatements.put(this.sqlCounter,"COMMIT"); 
      this.sqlCounter++; 

      BufferedWriter out = new BufferedWriter(new java.io.FileWriter(this.configFile.getProperty("SQL_FILE").toString())); 

      for(int i = 0; i < this.sqlStatements.size(); i++){ 

       out.write(this.sqlStatements.get(i) + ";" + "\n"); 

      } 

      //close file connection 
      out.close(); 
      System.out.println("End transaction"); 

     } catch (Exception ex) { 
      System.out.println(); 
      System.out.println("Message: "+ex.getMessage()); 
      if(ex.getMessage().trim().contains("Communications link failure")){ 
       System.out.println("Check there is a mysql connection and retry"); 
       System.out.println(); 
       System.exit(0); 

      }else{ 

       Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex); 

       //we've errored so we need to toll back the connection. 
       dbConn.rollback(); 

       //we now insert a message into the audit log. 

       String auditSQL = "INSERT INTO auditlog (username, date_added, message, guid, type)" + "VALUES('mcgeotools', now(), ?, md5(now()), ?)"; 

       PreparedStatement auditStmt = dbConn.prepareStatement(auditSQL); 

       //we want to know which survey failed to import and we need the stacktrace message. 
       String auditMessage = "Error whilst populating Survey " + typeName + " with error message : " + ex.getMessage(); 

       auditStmt.setString(1, auditMessage); 
       auditStmt.setString(2, "error"); //error 

       auditStmt.execute(); 

       dbConn.commit(); 
      } 

     } finally { 

      //close the iterator 
      iterator.close(); 

      //commit any transaction and close the connection to the database if it is open. 
      if (dbConn != null && !dbConn.isClosed()) { 
       try { 
        dbConn.commit(); 
        dbConn.close(); 
       } catch (Exception dbex) { 
        System.out.println("Communications failure, check there is a connection to mysql"); 
        Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, dbex); 
       } 
      } 

      //close file connection 

     } 


     return surveyDbId; 
    } 

    /** 
    * Get the coordinate system that is used in the shape file 
    * 
    * @param String shpFilePath 
    * @return String 
    */ 
    private String getCoordinateSystem(String shpFilePath) throws MalformedURLException, IOException { 
     String coordType = null; 
     ShpFiles shapeFiles = new ShpFiles(shpFilePath); 
     PrjFileReader fileReader = new PrjFileReader(shapeFiles); 
     CoordinateReferenceSystem coordSystem = fileReader.getCoodinateSystem(); 
     coordType = coordSystem.getName().toString(); 
     return coordType; 
    } 
} 

@Andre lỗi

Feb 22, 2013 12:03:54 PM org.geotools.data.shapefile.ng.files.ShpFiles logCurrentLockers 
SEVERE: The following locker still has a lock: read on file:/tmp/24/FozDoAmazonasPhase2.shp by org.geotools.data.shapefile.ng.shp.ShapefileReader 
Feb 22, 2013 12:03:54 PM org.geotools.data.shapefile.ng.files.ShpFiles logCurrentLockers 
SEVERE: The following locker still has a lock: read on file:/tmp/24/FozDoAmazonasPhase2.shx by org.geotools.data.shapefile.ng.shp.IndexFile 
Feb 22, 2013 12:03:54 PM org.geotools.data.shapefile.ng.files.ShpFiles logCurrentLockers 
SEVERE: The following locker still has a lock: read on file:/tmp/24/FozDoAmazonasPhase2.dbf by org.geotools.data.shapefile.ng.dbf.DbaseFileReader 
Feb 22, 2013 12:04:39 PM com.spectrumasa.mcgeotools.App main 
SEVERE: null 
java.lang.IllegalArgumentException: Expected requestor [email protected] to have locked the url but it does not hold the lock for the URL 
    at org.geotools.data.shapefile.ng.files.ShpFiles.unlockRead(ShpFiles.java:433) 
    at org.geotools.data.shapefile.ng.files.FileChannelDecorator.implCloseChannel(FileChannelDecorator.java:149) 
    at java.nio.channels.spi.AbstractInterruptibleChannel.close(AbstractInterruptibleChannel.java:114) 
    at org.geotools.data.shapefile.ng.dbf.DbaseFileReader.close(DbaseFileReader.java:279) 
    at org.geotools.data.shapefile.ng.ShapefileFeatureReader.close(ShapefileFeatureReader.java:248) 
    at org.geotools.data.store.ContentFeatureCollection$WrappingFeatureIterator.close(ContentFeatureCollection.java:227) 
    at com.spectrumasa.mcgeotools.convert.Converter.runConvert(Converter.java:487) 
    at com.spectrumasa.mcgeotools.App.main(App.java:100) 
+1

bạn có đóng FileReader để giải phóng tệp không? – Hekmatof

+0

ý của bạn là gì? Tôi chưa mở tập tin. Tôi chạy lệnh trong cli – shorif2000

+1

Tôi cũng nghĩ bạn đã đóng các tệp của mình? – AlexWien

Trả lời

1

Bạn cần đóng PrjFileReader trong phương thức getCoordinateSystem():

private String getCoordinateSystem(String shpFilePath) throws MalformedURLException, IOException { 
    PrjFileReader fileReader = null 
    try { 
     ShpFiles shapeFiles = new ShpFiles(shpFilePath); 
     fileReader = new PrjFileReader(shapeFiles); 
     CoordinateReferenceSystem coordSystem = fileReader.getCoodinateSystem(); 
     String coordType = coordSystem.getName().toString(); 
     return coordType; 
    } finally { 
     if (fileReader != null) { 
      fileReader.close(); 
     } 
    } 
} 
+0

Tôi đã thử thay vì 1 lỗi nghiêm trọng. Tôi nhận được nó 3 lần bây giờ. Tôi đã sao chép lỗi ở trên cùng – shorif2000

Các vấn đề liên quan