| /* |
| * 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.ofbiz.base.util; |
| |
| import java.io.File; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.ofbiz.base.component.ComponentConfig; |
| |
| |
| /** |
| * Java Source Parsing Utilities |
| * |
| * NOTE: the approach here is not the best and it may be better to use a parser, line one based on antlr, or using a Java Bytecode parser to look at .class files. |
| * |
| */ |
| public class UtilJavaParse { |
| |
| public static final String module = UtilJavaParse.class.getName(); |
| |
| public static String findRealPathAndFileForClass(String fullyQualifiedClassName) { |
| // search through the component directories, in the src directory for each, using the class path as the path within it |
| |
| String sourceSubPath = fullyQualifiedClassName.substring(0, fullyQualifiedClassName.lastIndexOf(".")).replace('.', File.separatorChar); |
| String classFileName = fullyQualifiedClassName.substring(fullyQualifiedClassName.lastIndexOf(".")+1) + ".java"; |
| |
| Collection<ComponentConfig> allComponentConfigs = ComponentConfig.getAllComponents(); |
| for (ComponentConfig cc: allComponentConfigs) { |
| String rootDirectory = cc.getRootLocation(); |
| if (!rootDirectory.endsWith(File.separatorChar + "")) rootDirectory += File.separatorChar; |
| rootDirectory += "src" + File.separatorChar; |
| |
| File rootDirFile = new File(rootDirectory); |
| if (!rootDirFile.exists()) { |
| // no src directory, move along |
| continue; |
| } |
| |
| String classDir = rootDirectory + sourceSubPath; |
| File classDirFile = new File(classDir); |
| if (!classDirFile.exists()) { |
| // no src class sub-directory, move along |
| continue; |
| } |
| |
| String fullPathAndFile = classDir + File.separatorChar + classFileName; |
| File classFile = new File(fullPathAndFile); |
| if (classFile.exists()) { |
| if (Debug.verboseOn()) Debug.logVerbose("In findRealPathAndFileForClass for [" + fullyQualifiedClassName + "]: [" + fullPathAndFile + "]", module); |
| return fullPathAndFile; |
| } |
| } |
| |
| return null; |
| } |
| |
| public static int findServiceMethodBlockStart(String methodName, String javaFile) { |
| if (Debug.verboseOn()) Debug.logVerbose("In findServiceMethodBlockStart for " + methodName, module); |
| |
| // starts with something like this: public static Map exportServiceEoModelBundle(DispatchContext dctx, Map context) { |
| |
| // start with the main pattern |
| int methodNameIndex = javaFile.indexOf("public static Map " + methodName + "(DispatchContext dctx, Map context) {"); |
| // try a little less... and some nice messy variations... |
| if (methodNameIndex < 0) methodNameIndex = javaFile.indexOf(" Map " + methodName + "(DispatchContext "); |
| if (methodNameIndex < 0) methodNameIndex = javaFile.indexOf(" Map " + methodName + "(DispatchContext "); |
| if (methodNameIndex < 0) methodNameIndex = javaFile.indexOf(" Map " + methodName + " (DispatchContext "); |
| if (methodNameIndex < 0) methodNameIndex = javaFile.indexOf(" Map " + methodName + "(DispatchContext "); |
| if (methodNameIndex < 0) methodNameIndex = javaFile.indexOf(" Map " + methodName + " (DispatchContext "); |
| |
| // not found! |
| if (methodNameIndex < 0) return -1; |
| |
| // find the open brace and return its position |
| return javaFile.indexOf("{", methodNameIndex); |
| } |
| |
| public static int findEndOfBlock(int blockStart, String javaFile) { |
| //Debug.logInfo("In findEndOfBlock for blockStart " + blockStart, module); |
| |
| int nextOpen = javaFile.indexOf("{", blockStart+1); |
| int nextClose = javaFile.indexOf("}", blockStart+1); |
| if (nextOpen > 0 && nextClose > 0 && nextClose > nextOpen) { |
| javaFile.substring(nextOpen, nextClose); |
| } |
| // if no close, end with couldn't find |
| if (nextClose < 0) return -1; |
| // while nextOpen is found and is before the next close, then recurse (list |
| while (nextOpen > -1 && nextOpen < nextClose) { |
| int endOfSubBlock = findEndOfBlock(nextOpen, javaFile); |
| if (endOfSubBlock < 0) return -1; |
| nextOpen = javaFile.indexOf("{", endOfSubBlock+1); |
| nextClose = javaFile.indexOf("}", endOfSubBlock+1); |
| //Debug.logInfo("In loop in findEndOfBlock for nextOpen=" + nextOpen + ", nextClose=" + nextClose + ", endOfSubBlock=" + endOfSubBlock, module); |
| } |
| |
| // at this point there should be no nextOpen or nextOpen is after the nextClose, meaning we're at the end of the block |
| return nextClose; |
| } |
| |
| // FIXME: Not thread safe |
| public static Set<String> serviceMethodNames = new HashSet<String>(); |
| static { |
| serviceMethodNames.add("runSync"); |
| serviceMethodNames.add("runSyncIgnore"); |
| serviceMethodNames.add("runAsync"); |
| serviceMethodNames.add("runAsyncWait"); |
| serviceMethodNames.add("registerCallback"); |
| serviceMethodNames.add("schedule"); // NOTE: the service name may be the 1st, 2nd or 3rd param for variations on this |
| serviceMethodNames.add("addRollbackService"); |
| serviceMethodNames.add("addCommitService"); |
| } |
| public static Set<String> findServiceCallsInBlock(int blockStart, int blockEnd, String javaFile) { |
| Set<String> serviceNameSet = new HashSet<String>(); |
| |
| int dispatcherIndex = javaFile.indexOf("dispatcher.", blockStart+1); |
| while (dispatcherIndex > 0 && dispatcherIndex < blockEnd) { |
| // verify it is a call we're looking for |
| int openParenIndex = javaFile.indexOf("(", dispatcherIndex); |
| String curMethodName = javaFile.substring(dispatcherIndex + 11, openParenIndex).trim(); |
| if (serviceMethodNames.contains(curMethodName)) { |
| // find the service name |
| int openQuoteIndex = javaFile.indexOf("\"", openParenIndex); |
| int closeQuoteIndex = javaFile.indexOf("\"", openQuoteIndex+1); |
| if (openQuoteIndex - openParenIndex <= 3 && openQuoteIndex >= 0 && closeQuoteIndex >= 0) { |
| //more than two spaces/chars between quote and open paren... consider it something other than what we are looking for |
| String serviceName = javaFile.substring(openQuoteIndex+1, closeQuoteIndex).trim(); |
| //Debug.logInfo("In findServiceCallsInBlock found serviceName [" + serviceName + "]", module); |
| serviceNameSet.add(serviceName); |
| } |
| } |
| |
| dispatcherIndex = javaFile.indexOf("dispatcher.", openParenIndex); |
| } |
| |
| return serviceNameSet; |
| } |
| |
| // FIXME: Not thread safe |
| public static Set<String> entityMethodNames = new HashSet<String>(); |
| static { |
| entityMethodNames.add("getModelEntity"); |
| entityMethodNames.add("getEntityGroupName"); |
| entityMethodNames.add("getModelEntityMapByGroup"); |
| entityMethodNames.add("getGroupHelperName"); |
| entityMethodNames.add("getEntityHelperName"); |
| entityMethodNames.add("getEntityHelper"); |
| |
| entityMethodNames.add("makeValue"); |
| entityMethodNames.add("makeValueSingle"); |
| entityMethodNames.add("makeValidValue"); |
| entityMethodNames.add("makePK"); |
| entityMethodNames.add("makePKSingle"); |
| |
| entityMethodNames.add("create"); |
| entityMethodNames.add("createSingle"); |
| entityMethodNames.add("removeByAnd"); |
| entityMethodNames.add("removeByCondition"); |
| |
| entityMethodNames.add("create"); |
| entityMethodNames.add("createSingle"); |
| entityMethodNames.add("removeByAnd"); |
| entityMethodNames.add("removeByCondition"); |
| entityMethodNames.add("storeByCondition"); |
| entityMethodNames.add("removeAll"); |
| entityMethodNames.add("findOne"); |
| entityMethodNames.add("findByPrimaryKey"); |
| entityMethodNames.add("findByPrimaryKeyCache"); |
| entityMethodNames.add("findAllCache"); |
| entityMethodNames.add("findByAnd"); |
| entityMethodNames.add("findByOr"); |
| entityMethodNames.add("findByAndCache"); |
| entityMethodNames.add("findByLike"); |
| entityMethodNames.add("findByCondition"); |
| entityMethodNames.add("findByConditionCache"); |
| entityMethodNames.add("findListIteratorByCondition"); |
| entityMethodNames.add("find"); |
| entityMethodNames.add("findList"); |
| entityMethodNames.add("findCountByAnd"); |
| entityMethodNames.add("findCountByCondition"); |
| } |
| public static Set<String> findEntityUseInBlock(int blockStart, int blockEnd, String javaFile) { |
| Set<String> entityNameSet = new HashSet<String>(); |
| |
| int delegatorIndex = javaFile.indexOf("delegator.", blockStart+1); |
| while (delegatorIndex > 0 && delegatorIndex < blockEnd) { |
| // verify it is a call we're looking for |
| int openParenIndex = javaFile.indexOf("(", delegatorIndex); |
| String curMethodName = javaFile.substring(delegatorIndex + 10, openParenIndex).trim(); |
| if (entityMethodNames.contains(curMethodName)) { |
| // find the entity name |
| int openQuoteIndex = javaFile.indexOf("\"", openParenIndex); |
| int closeQuoteIndex = javaFile.indexOf("\"", openQuoteIndex+1); |
| if (openQuoteIndex - openParenIndex <= 3 && openQuoteIndex >= 0 && closeQuoteIndex >= 0) { |
| //more than two spaces/chars between quote and open paren... consider it something other than what we are looking for |
| String entityName = javaFile.substring(openQuoteIndex+1, closeQuoteIndex).trim(); |
| //Debug.logInfo("In findServiceCallsInBlock found valid entityName [" + entityName + "]", module); |
| entityNameSet.add(entityName); |
| } |
| } |
| |
| delegatorIndex = javaFile.indexOf("delegator.", openParenIndex); |
| } |
| |
| return entityNameSet; |
| } |
| |
| public static String stripComments(String javaFile) { |
| StringBuilder strippedFile = new StringBuilder(); |
| int commentOpen = javaFile.indexOf("/*"); |
| int commentClose = javaFile.indexOf("*/"); |
| if (commentOpen > -1) { |
| if (commentOpen > 0) { |
| strippedFile.append(javaFile.substring(0, commentOpen)); |
| } |
| commentOpen = javaFile.indexOf("/*", commentClose); |
| while (commentOpen > -1) { |
| strippedFile.append(javaFile.substring(commentClose + 2, commentOpen)); |
| commentClose = javaFile.indexOf("*/", commentOpen); |
| commentOpen = javaFile.indexOf("/*", commentClose); |
| } |
| strippedFile.append(javaFile.substring(commentClose + 2)); |
| } else { |
| strippedFile.append(javaFile); |
| } |
| |
| String lineSeparator = System.getProperty("line.separator"); |
| int lineComment = strippedFile.indexOf("//"); |
| while (lineComment > -1) { |
| int endOfLine = strippedFile.indexOf(lineSeparator, lineComment); |
| strippedFile.delete(lineComment, endOfLine); |
| lineComment = strippedFile.indexOf("//", lineComment); |
| } |
| return strippedFile.toString(); |
| } |
| } |