arcgissamples\geodatabase\TimeStamperRunner.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop
Time Stamper custom Java class extension
arcgissamples\geodatabase\TimeStamperRunner.java
/* Copyright 2015 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions at <your ArcGIS install location>/DeveloperKit10.4/userestrictions.txt.
* 
*/
package arcgissamples.geodatabase;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory;
import com.esri.arcgis.geodatabase.Feature;
import com.esri.arcgis.geodatabase.FeatureClass;
import com.esri.arcgis.geodatabase.Field;
import com.esri.arcgis.geodatabase.Fields;
import com.esri.arcgis.geodatabase.GeometryDef;
import com.esri.arcgis.geodatabase.Workspace;
import com.esri.arcgis.geodatabase.esriFeatureType;
import com.esri.arcgis.geodatabase.esriFieldType;
import com.esri.arcgis.geodatabase.esriSchemaLock;
import com.esri.arcgis.geometry.GeographicCoordinateSystem;
import com.esri.arcgis.geometry.Point;
import com.esri.arcgis.geometry.SpatialReferenceEnvironment;
import com.esri.arcgis.geometry.esriGeometryType;
import com.esri.arcgis.geometry.esriSRGeoCSType;
import com.esri.arcgis.interop.extn.ArcGISExtension;
import com.esri.arcgis.interop.extn.Bootstrapper;
import com.esri.arcgis.system.AoInitialize;
import com.esri.arcgis.system.EngineInitializer;
import com.esri.arcgis.system.PropertySet;
import com.esri.arcgis.system.UID;
import com.esri.arcgis.system.esriLicenseProductCode;
import com.esri.arcgis.system.esriLicenseStatus;

public class TimeStamperRunner
{
    private static String outputPath = null;
    private Class ceClass = null;

    public static void main(String[] args)
    {
      try{
      //Get the ArcGIS Desktop runtime, if it is available
        String arcObjectsHome = System.getenv("AGSENGINEJAVA");
        
        //If the ArcGIS Desktop runtime is not available, then report appropriate error to developer
        if(arcObjectsHome == null){
            System.err.println("The TimeStamper sample is designed to work with ArcGIS Engine installed.");
            System.err.println("You must install ArcGIS Engine and deploy the TimeStamperExt.jar as instructed " +
                      "in this sample's ReadMe.htm file.");
            System.err.println("Exiting execution of this sample...");
            System.exit(0);
        }

        String extensionJar = arcObjectsHome + "java" + File.separator + "lib" + File.separator + "ext" + File.separator + 
                      "TimeStamperExt.jar";
      
        TimeStamperRunner driver = new TimeStamperRunner();
          
        //get output folder
            outputPath = getOutputDir();

            if(driver.isJarFileValid(extensionJar)){
                driver.ceClass = driver.getCEClass(extensionJar).get(0);
            }
          
            EngineInitializer.initializeEngine();
            AoInitialize aoInit = new AoInitialize();
                
            driver.initializeArcGISLicenses(aoInit);
                
            driver.driveExtension();

            aoInit.shutdown();
        }
        catch (Exception e){e.printStackTrace();}
    }
    
    void initializeArcGISLicenses(AoInitialize aoInit) {
    try {
      if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeEngine) 
          == esriLicenseStatus.esriLicenseAvailable)
        aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
    } catch (Exception e) {e.printStackTrace();}
  }

    /**
   * Convenience method to generate an output directory based on the operating
   * system that the sample is being executed on. 
   * 
   * @return A path to the new directory is return
   */
  private static String getOutputDir() {
    String userDir;
    
    //Get the operating systems user profile or home location depending
    //on which operating system this sample is executed on.
    if(System.getProperty("os.name").toLowerCase().indexOf("win") > -1){
      userDir = System.getenv("UserProfile");
    }else{
      userDir = System.getenv("HOME");
    }
      
    String outputDir = userDir + File.separator + "arcgis_sample_output";
    
    System.out.println("Creating output directory - " + outputDir);
    
    new File(outputDir).mkdir();
    
    return outputDir;
  }

  public void driveExtension() throws Exception
    {
    System.out.println("Starting TimeStamperRunner...\n");

        System.out.print("Initializing data paths...");
        String fgdbName = "timestamper.gdb";
        System.out.println("Done.");

        System.out.print("Creating output folder " + outputPath + " if it does not exist...");
        createFolder(outputPath);
        System.out.println("Done.");

        System.out.print("Creating local File GDB...");
        FileGDBWorkspaceFactory wsFactory = new FileGDBWorkspaceFactory();
        wsFactory.create(outputPath, fgdbName, null, 0);
        System.out.println("Done.");
    System.out.println("Created a File GDB in the following location: " + outputPath + File.separator + fgdbName);
    
        //create a fc in above file gdb and associate class extension with it
        System.out.print("Creating a feature class in local File GDB...");
        Workspace ws = (Workspace) wsFactory.openFromFile(outputPath + File.separator + fgdbName, 0);

        Fields fields = new Fields();

        //iod field
        Field field = new Field();
        field.setName("OBJECTID");
        field.setType(esriFieldType.esriFieldTypeOID);
        fields.addField(field);
        field = null;

        //shape field
        field = new Field();

        GeometryDef gdef = new GeometryDef();
        gdef.setGeometryType(esriGeometryType.esriGeometryPoint);
        gdef.setHasM(false);
        gdef.setHasZ(false);

        SpatialReferenceEnvironment sre = new SpatialReferenceEnvironment();
        GeographicCoordinateSystem gcs = (GeographicCoordinateSystem) sre.createGeographicCoordinateSystem(esriSRGeoCSType.esriSRGeoCS_NAD1983);
        gcs.setDomain(-400, 400, -400, 400);

        gdef.setSpatialReferenceByRef(gcs);

        field.setName("shape");
        field.setType(esriFieldType.esriFieldTypeGeometry);
        field.setGeometryDefByRef(gdef);
        fields.addField(field);
        field = null;

        //source id field
        field = new Field();
        field.setName("SourceID");
        field.setType(esriFieldType.esriFieldTypeSmallInteger);
        fields.addField(field);
        field = null;

        //creation Field
        String creationFieldName = "Created";
        field = new Field();
        field.setName(creationFieldName);
        field.setType(esriFieldType.esriFieldTypeDate);
        fields.addField(field);
        field = null;

        //modification Field
        String modificationFieldName = "ModifiedLast";
        field = new Field();
        field.setName(modificationFieldName);
        field.setType(esriFieldType.esriFieldTypeDate);
        fields.addField(field);
        field = null;

        //user Field
        String userFieldName = "ModifiedBy";
        field = new Field();
        field.setName(userFieldName);
        field.setType(esriFieldType.esriFieldTypeString);
        fields.addField(field);
        field = null;

        //create and return feature class
        String fcName = "timeStamperEvents";
        FeatureClass fc = new FeatureClass(ws.createFeatureClass(fcName, fields, null, null, esriFeatureType.esriFTSimple, "shape", "default"));
        System.out.println("Done.");

        System.out.print("Adding \"Time Stamper\" extension to " + fcName + "...");
        if(fc.getEXTCLSID() == null)
        {
            fc.changeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);

            // Create a new unique identifier object (UID) and assign the GUID to it.
            UID extUID = new UID();
            extUID.setValue(ceClass);

            PropertySet propertySet = new PropertySet();
            propertySet.setProperty("CREATION_FIELDNAME", creationFieldName);
            propertySet.setProperty("MODIFICATION_FIELDNAME", modificationFieldName);
            propertySet.setProperty("USER_FIELDNAME", userFieldName);

            fc.alterClassExtensionCLSID(extUID, propertySet);
            fc.changeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
        }
        else
        {
            System.out.println("Cannot alter EXTCLSID for feature class. One already exists");
        }

        System.out.println("Done.");

        System.out.print("Adding features to " + fcName + "...");
        ws.startEditing(false);
        ws.startEditOperation();

        Feature newFeature = null;
        try
        {
            //add feature 1
            newFeature = (Feature) fc.createFeature();

            Point point1 = new Point();
            point1.setSpatialReferenceByRef(fc.getSpatialReference());
            point1.setX(-82.794);
            point1.setY(40.162);

            newFeature.setShapeByRef(point1);
            newFeature.setValue(2, 1);
            newFeature.store();
            newFeature = null;

            //add feature 2
            newFeature = (Feature) fc.createFeature();

            Point point2 = new Point();
            point2.setSpatialReferenceByRef(fc.getSpatialReference());
            point2.setX(-81.394);
            point2.setY(41.511);

            newFeature.setShapeByRef(point2);
            newFeature.setValue(2, 2);
            newFeature.store();
            newFeature = null;

            //add feature 3
            newFeature = (Feature) fc.createFeature();

            Point point3 = new Point();
            point3.setSpatialReferenceByRef(fc.getSpatialReference());
            point3.setX(-84.286);
            point3.setY(41.598);

            newFeature.setShapeByRef(point3);
            newFeature.setValue(2, 3);
            newFeature.store();

            ws.stopEditOperation();
            ws.stopEditing(true);
        }
        catch(Exception e)
        {
            if(ws != null && ws.isBeingEdited())
            {
                ws.stopEditing(false);
            }

            e.printStackTrace();
        }
        System.out.println("Done.");

        System.out.println("\nTimeStamperRunner done.\n Please check the CREATION_FIELDNAME, MODIFICATION_FIELDNAME, " +
                "and USER_FIELDNAME fields in " + outputPath + "\\" + fgdbName + "\\" + fcName + " for time stamps for new features.");

        System.out.println("\nTimeStamperRunner Done.");
    }

  /*
   * Returns valid jar file path
   * @param jarFileName
   * @return
   */
  private boolean isJarFileValid(String jarFilePath) throws FileNotFoundException
  {
    if(jarFilePath.length() == 0 || jarFilePath == null)
    {
      System.err.println("Error: Jar file path is empty, null or it contains invalid/unsupported characters.");
      System.exit(-1);
    }
    else
    {      
      File jarFile = new File(jarFilePath);
      if(jarFile.exists())
      {
        if(!jarFile.isFile() && !jarFilePath.endsWith(".jar"))
        {
          throw new FileNotFoundException("Jar file " + jarFile + " not found. Please verify if name of jar file containing Class Extension is correct.");
        }
      }
    }
    
    return true;
  }
  
  /*
   * Retrieve list of valid SOE classes in specified jar file
   */
  private ArrayList<Class> getCEClass(String jarFilePath)
  {
    ArrayList<Class> ceClassList = new ArrayList<Class>(5);
    
    //validate input path
    if(System.getProperty("os.name").toLowerCase().startsWith("windows"))
    {
      if(jarFilePath.contains("Program Files"))
      {
        jarFilePath = jarFilePath.replace("Program Files", "Progra~1");
      }
      else if(jarFilePath.contains("Program Files (x86)"))
      {
        jarFilePath = jarFilePath.replace("Program Files (x86)", "Progra~2");
      } 
    }    
        
    //validate file indicated by jar file name. 
    try
    {        
      //load classes present inside jar file into memory
      Bootstrapper.loadExtensionJar(jarFilePath);        
      
      //retrieve individual contents of jar file
      JarFile jarFile = new JarFile(jarFilePath);
      Enumeration<JarEntry> jarContents = jarFile.entries();
      while (jarContents.hasMoreElements())
      {
        ZipEntry zipEntry = (ZipEntry) jarContents.nextElement();
        if(!zipEntry.isDirectory())
        {
          //ignore current file if it does not end with .class
          String fileName = zipEntry.getName();
          if(fileName.endsWith(".class"))
          {
            //retrieve the Class object for current class file
            String ceFullyQualifiedName = fileName.replace('/', '.').substring(0, fileName.length() -  ".class".length());
            Class classDef = Class.forName(ceFullyQualifiedName);
            
            //consider class only if its not an interface and its annotated with ArcGISExtension
            if(!classDef.isInterface() && classDef.isAnnotationPresent(ArcGISExtension.class))
            {
              //add the class to a list
              ceClassList.add(classDef);
            }
          }
        }
      }
      
      //trim the list
      ceClassList.trimToSize();
      
      //if list is of size 0
      if(ceClassList.size() <= 0)
      {
        System.err.println("\nError: No .class files or .class files containing Class Extension found in " + jarFilePath);
      }        
      
      //return it
      return ceClassList;
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    catch(ClassNotFoundException ce)
    {
      ce.printStackTrace();
    }
    

    return null;
  }    
  
    /**
     * Creates a new directory
     * @param pathName String
     */
    public void createFolder(String pathName)
    {
        File f = new File(pathName);
        if (!f.exists())
        {
            f.mkdir();
        }
    }

    /**
     * Empties specified directory of all files
     * @param dirName String
     */
    public void emptyFolder(String dirName, boolean includeSubFolder) throws Exception
    {
        File src = new File(dirName);
        if (src.isDirectory() && src.exists())
        {
            File list[] = src.listFiles();
            for (int i = 0; i < list.length; i++)
            {
                if (includeSubFolder && list[i].isDirectory())
                {
                    emptyFolder(list[i].getPath(), includeSubFolder);
                    list[i].delete();
                }
                else
                {
                    list[i].delete();
                }
            }
        }
        else
        {
            throw new Exception("FeatureValidatorDriver.emptyFolder() - " + dirName + " is not a directory or does not exist.");
        }
    }

    /**
     * Empties specified directory of all files
     * @param dirName String
     */
    public void deleteFolder(String dirName) throws Exception
    {
        File src = new File(dirName);
        if (src.isDirectory() && src.exists())
        {
            File list[] = src.listFiles();
            for (int i = 0; i < list.length; i++)
            {
                if (list[i].isDirectory())
                {
                    emptyFolder(list[i].getPath(), true);
                    list[i].delete();
                }
                else
                {
                    list[i].delete();
                }
            }
            src.delete();
        }
        else
        {
            src.delete();
        }
    }

    /**
     * Empties specified directory of all files
     * @param dirName String
     */
    public void deleteFile(String fullyQualifiedFileName) throws Exception
    {
        File file = new File(fullyQualifiedFileName);
        if(!file.isDirectory() && file.exists())
        {
            file.delete();
        }
        else
        {
            throw new Exception("MatrixUtil.deleteFile() - File " + fullyQualifiedFileName + " does not exist or is a directory.");
        }
    }
}