001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.cmis; 029 030import org.opencms.main.CmsLog; 031import org.opencms.util.CmsStringUtil; 032 033import java.lang.reflect.InvocationHandler; 034import java.lang.reflect.InvocationTargetException; 035import java.lang.reflect.Method; 036import java.lang.reflect.Proxy; 037import java.math.BigInteger; 038import java.util.ArrayList; 039import java.util.HashSet; 040import java.util.List; 041import java.util.Map; 042import java.util.Set; 043 044import org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory; 045import org.apache.chemistry.opencmis.commons.server.CallContext; 046import org.apache.chemistry.opencmis.commons.server.CmisService; 047import org.apache.chemistry.opencmis.server.support.wrapper.ConformanceCmisServiceWrapper; 048import org.apache.commons.logging.Log; 049 050/** 051 * The factory class for creating the OpenCms CMIS service instances.<p> 052 */ 053public class CmsCmisServiceFactory extends AbstractServiceFactory { 054 055 /** 056 * An invocation handler which wraps a service and is used for debugging/logging CMIS service calls.<p> 057 */ 058 static class LoggingServiceProxy implements InvocationHandler { 059 060 /** The CMIS service interfaces. */ 061 private static Set<Class<?>> m_serviceInterfaces = new HashSet<Class<?>>(); 062 063 /** The wrapped service. */ 064 private CmisService m_service; 065 066 /** 067 * Creates a instance.<p> 068 * 069 * @param service the service to wrap 070 */ 071 public LoggingServiceProxy(CmisService service) { 072 073 m_service = service; 074 } 075 076 static { 077 for (Class<?> svcInterface : CmisService.class.getInterfaces()) { 078 m_serviceInterfaces.add(svcInterface); 079 } 080 } 081 082 /** 083 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) 084 */ 085 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 086 087 try { 088 // CmisService defines some methods in addition to its base interfaces which don't correspond to CMIS service calls 089 090 boolean isServiceCall = m_serviceInterfaces.contains(method.getDeclaringClass()); 091 if (isServiceCall) { 092 LOG.info("CMIS service call: " + getCallString(method, args)); 093 } 094 Object result = method.invoke(m_service, args); 095 if (isServiceCall && LOG.isDebugEnabled()) { 096 // This can generate a *VERY LARGE AMOUNT* of data in the log file, don't activate the debug channel 097 // unless you really need to 098 LOG.debug("Returned '" + result + "'"); 099 } 100 return result; 101 } catch (InvocationTargetException e) { 102 Throwable cause = e.getCause(); 103 LOG.info(cause.getLocalizedMessage(), cause); 104 throw cause; 105 } 106 } 107 108 /** 109 * Creates a string representation of a given method call, which is used for logging.<p> 110 * 111 * @param method the method 112 * @param args the method call arguments 113 * 114 * @return a string representation of the method call 115 */ 116 private String getCallString(Method method, Object[] args) { 117 118 List<String> tokens = new ArrayList<String>(); 119 tokens.add(method.getName()); 120 if ((args != null) && (args.length > 0)) { 121 tokens.add("=>"); 122 for (Object arg : args) { 123 tokens.add("'" + arg + "'"); 124 } 125 } 126 return CmsStringUtil.listAsString(tokens, " "); 127 } 128 } 129 130 /** The logger for this class. */ 131 protected static final Log LOG = CmsLog.getLog(CmsCmisServiceFactory.class); 132 133 /** Default value for maximum depth of objects to return. */ 134 private static final BigInteger DEFAULT_DEPTH_OBJECTS = BigInteger.valueOf(100); 135 136 /** Default value for maximum depth of types to return. */ 137 private static final BigInteger DEFAULT_DEPTH_TYPES = BigInteger.valueOf(-1); 138 139 /** Default value for maximum number of objects to return. */ 140 private static final BigInteger DEFAULT_MAX_ITEMS_OBJECTS = BigInteger.valueOf(200); 141 142 /** Default value for maximum number of types to return. */ 143 private static final BigInteger DEFAULT_MAX_ITEMS_TYPES = BigInteger.valueOf(50); 144 145 /** 146 * @see org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory#destroy() 147 */ 148 @Override 149 public void destroy() { 150 151 // do nothing for now 152 } 153 154 /** 155 * @see org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory#getService(org.apache.chemistry.opencmis.commons.server.CallContext) 156 */ 157 @Override 158 public CmisService getService(CallContext context) { 159 160 CmsCmisService service = new CmsCmisService(context); 161 CmisService proxyService = (CmisService)Proxy.newProxyInstance( 162 this.getClass().getClassLoader(), 163 new Class[] {CmisService.class}, 164 new LoggingServiceProxy(service)); 165 ConformanceCmisServiceWrapper wrapperService = new ConformanceCmisServiceWrapper( 166 proxyService, 167 DEFAULT_MAX_ITEMS_TYPES, 168 DEFAULT_DEPTH_TYPES, 169 DEFAULT_MAX_ITEMS_OBJECTS, 170 DEFAULT_DEPTH_OBJECTS); 171 return wrapperService; 172 } 173 174 /** 175 * @see org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory#init(java.util.Map) 176 */ 177 @Override 178 public void init(Map<String, String> parameters) { 179 180 // do nothing for now 181 } 182}