content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  package org.apache.chemistry.opencmis.bridge;
  
  import java.io.File;
  import java.math.BigInteger;
  import java.util.Map;
  
  import org.apache.chemistry.opencmis.commons.impl.ClassLoaderUtil;
  import org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory;
  import org.apache.chemistry.opencmis.commons.server.CallContext;
  import org.apache.chemistry.opencmis.commons.server.CmisService;
  import org.apache.chemistry.opencmis.server.support.wrapper.CallContextAwareCmisService;
  import org.apache.chemistry.opencmis.server.support.wrapper.ConformanceCmisServiceWrapper;
  
  public abstract class AbstractBridgeServiceFactory extends AbstractServiceFactory {
  
      public static final String BRIDGE_TEMP_DIRECTORY = "bridge.tempDirectory";
      public static final String BRIDGE_MEMORY_THERESHOLD = "bridge.memoryThreshold";
      public static final String BRIDGE_MAX_CONTENT_SIZE = "bridge.maxContentSize";
  
      public static final String SERVICE_CLASS = "service.class";
      public static final String SERVICE_DEFAULT_MAX_ITEMS_OBJECTS = "service.defaultMaxItems";
      public static final String SERVICE_DEFAULT_DEPTH_OBJECTS = "service.defaultDepth";
      public static final String SERVICE_DEFAULT_MAX_ITEMS_TYPES = "service.defaultTypesMaxItems";
      public static final String SERVICE_DEFAULT_DEPTH_TYPES = "service.defaultTypesDepth";
  
      private static final BigInteger DEFAULT_MAX_ITEMS_OBJECTS = BigInteger.valueOf(100000);
      private static final BigInteger DEFAULT_DEPTH_OBJECTS = BigInteger.valueOf(100);
      private static final BigInteger DEFAULT_MAX_ITEMS_TYPES = BigInteger.valueOf(1000);
      private static final BigInteger DEFAULT_DEPTH_TYPES = BigInteger.valueOf(10);
  
      private ThreadLocal<CallContextAwareCmisService> threadLocalService = new ThreadLocal<CallContextAwareCmisService>();
  
      private Map<String, String> parameters;
  
      private Class<?> serviceClass;
  
      private BigInteger defaultMaxItems;
      private BigInteger defaultDepth;
      private BigInteger defaultTypesMaxItems;
      private BigInteger defaultTypesDepth;
  
      private File tempDirectory;
      private int memoryThreshold;
      private long maxContentSize;
  
      @Override
      public void init(Map<String, String> parameters) {
          this.parameters = parameters;
  
          // get bridge configuration
          String tempDirectoryStr = parameters.get(BRIDGE_TEMP_DIRECTORY);
          tempDirectory = tempDirectoryStr == null || tempDirectoryStr.trim().length() == 0 ? super.getTempDirectory()
                  : new File(tempDirectoryStr.trim());
  
          try {
              String memoryThresholdStr = parameters.get(BRIDGE_MEMORY_THERESHOLD);
              memoryThreshold = memoryThresholdStr == null || memoryThresholdStr.trim().length() == 0 ? super
                      .getMemoryThreshold() : Integer.parseInt(memoryThresholdStr.trim());
  
              String maxContentSizeStr = parameters.get(BRIDGE_MAX_CONTENT_SIZE);
              maxContentSize = maxContentSizeStr == null || maxContentSizeStr.trim().length() == 0 ? super
                      .getMaxContentSize() : Long.parseLong(maxContentSizeStr.trim());
          } catch (NumberFormatException e) {
              throw new RuntimeException("Could not parse bride configuration values: " + e.getMessage(), e);
          }
  
          // find service class
          String className = parameters.get(SERVICE_CLASS);
          if (className == null || className.trim().length() == 0) {
              throw new RuntimeException("Service class name is not set!");
          }
  
          try {
              serviceClass = ClassLoaderUtil.loadClass(className);
          } catch (ClassNotFoundException e) {
              throw new RuntimeException("Service class name cannot be found: " + e.getMessage(), e);
          }
  
          if (serviceClass.isAssignableFrom(FilterCmisService.class)) {
              throw new RuntimeException("Service class is not a sub class of FilterCmisService!");
          }
  
          // get service defaults
          try {
              defaultMaxItems = getBigIntegerParameter(SERVICE_DEFAULT_MAX_ITEMS_OBJECTS, DEFAULT_MAX_ITEMS_OBJECTS);
              defaultDepth = getBigIntegerParameter(SERVICE_DEFAULT_DEPTH_OBJECTS, DEFAULT_DEPTH_OBJECTS);
              defaultTypesMaxItems = getBigIntegerParameter(SERVICE_DEFAULT_MAX_ITEMS_TYPES, DEFAULT_MAX_ITEMS_TYPES);
              defaultTypesDepth = getBigIntegerParameter(SERVICE_DEFAULT_DEPTH_TYPES, DEFAULT_DEPTH_TYPES);
          } catch (NumberFormatException e) {
              throw new RuntimeException("Could not parse service default values: " + e.getMessage(), e);
          }
      }
  
      @Override
      public CmisService getService(CallContext context) {
          CallContextAwareCmisService service = threadLocalService.get();
          if (service == null) {
              service = new ConformanceCmisServiceWrapper(createService(context), defaultTypesMaxItems,
                      defaultTypesDepth, defaultMaxItems, defaultDepth);
              threadLocalService.set(service);
          }
  
          service.setCallContext(context);
  
          return service;
      }
  
      /**
       * Creates a new service instance.
       */
      protected abstract FilterCmisService createService(CallContext context);
  
      protected Class<?> getServiceClass() {
          return serviceClass;
      }
  
      protected Map<String, String> getParameters() {
          return parameters;
      }
  
      @Override
      public File getTempDirectory() {
          return tempDirectory;
      }
  
      @Override
      public int getMemoryThreshold() {
          return memoryThreshold;
      }
  
      @Override
      public long getMaxContentSize() {
          return maxContentSize;
      }
  
      /**
       * Gets a BigInteger parameter from the parameters.
       */
      protected BigInteger getBigIntegerParameter(String key, BigInteger def) {
          String value = parameters.get(key);
          if (value == null || value.trim().length() == 0) {
              return def;
          }
  
          return new BigInteger(value);
      }
  }
  