http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContext.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContext.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContext.java new file mode 100644 index 0000000..65a5bc9 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContext.java @@ -0,0 +1,42 @@ +/* + * 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.logging.log4j.audit.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(RequestContextConstraints.class) +public @interface RequestContext { + + String key(); + + boolean required() default false; + + /** + * The Constraints that apply to this key for the associated event. + * @return + */ + Constraint[] constraints() default {}; +}
http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContextConstraints.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContextConstraints.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContextConstraints.java new file mode 100644 index 0000000..13cd93d --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/RequestContextConstraints.java @@ -0,0 +1,31 @@ +/* + * 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.logging.log4j.audit.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Container for RequestContext constraints. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequestContextConstraints { + RequestContext[] value(); +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/Required.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/Required.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/Required.java new file mode 100644 index 0000000..b46c127 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/annotation/Required.java @@ -0,0 +1,30 @@ +/* + * 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.logging.log4j.audit.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks an attribute as being required in the audit event. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Required { +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManager.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManager.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManager.java new file mode 100644 index 0000000..112e4e0 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManager.java @@ -0,0 +1,42 @@ +/* + * 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.logging.log4j.audit.catalog; + +import org.apache.logging.log4j.catalog.api.Attribute; +import org.apache.logging.log4j.catalog.api.Event; +import org.apache.logging.log4j.catalog.api.EventAttribute; + +import java.util.List; +import java.util.Map; + +/** + * + */ +public interface CatalogManager { + + Event getEvent(String eventName); + + List<String> getRequiredContextAttributes(String eventName); + + List<String> getAttributeNames(String eventName); + + Map<String, Attribute> getAttributes(String eventName); + + Map<String, Attribute> getRequestContextAttributes(); + + Attribute getAttribute(String attributeName); +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManagerImpl.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManagerImpl.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManagerImpl.java new file mode 100644 index 0000000..f5ce826 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/catalog/CatalogManagerImpl.java @@ -0,0 +1,150 @@ +/* + * 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.logging.log4j.audit.catalog; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.audit.exception.AuditException; +import org.apache.logging.log4j.audit.util.NamingUtils; +import org.apache.logging.log4j.catalog.api.Attribute; +import org.apache.logging.log4j.catalog.api.CatalogData; +import org.apache.logging.log4j.catalog.api.Event; +import org.apache.logging.log4j.catalog.api.CatalogReader; +import org.apache.logging.log4j.catalog.api.EventAttribute; + +/** + * + */ +public class CatalogManagerImpl implements CatalogManager { + + private static Logger logger = LogManager.getLogger(CatalogManagerImpl.class); + + private volatile Map<String, CatalogInfo> infoMap; + + private Map<String, Attribute> requestContextAttributes = new HashMap<>(); + + private final Map<String, Attribute> attributeMap = new HashMap<>(); + + private static final String REQCTX = "ReqCtx_"; + + public CatalogManagerImpl(CatalogReader catalogReader) { + try { + infoMap = initializeData(catalogReader); + } catch (Exception ex) { + throw new AuditException("Unable to initialize catalog data", ex); + } + } + + @Override + public Event getEvent(String eventName) { + CatalogInfo info = infoMap.get(eventName); + return info != null ? info.event : null; + } + + @Override + public List<String> getRequiredContextAttributes(String eventName) { + return infoMap.get(eventName).requiredContextAttributes; + } + + @Override + public Map<String, Attribute> getAttributes(String eventName) { + return infoMap.get(eventName).attributes; + } + + @Override + public List<String> getAttributeNames(String eventName) { + return infoMap.get(eventName).attributeNames; + } + + @Override + public Attribute getAttribute(String name) { + return attributeMap.get(name); + } + + @Override + public Map<String, Attribute> getRequestContextAttributes() { + return requestContextAttributes; + } + + private Map<String, CatalogInfo> initializeData(CatalogReader catalogReader) throws Exception { + String catalog = catalogReader.readCatalog(); + JsonFactory factory = new JsonFactory(); + factory.enable(JsonParser.Feature.ALLOW_COMMENTS); + ObjectMapper mapper = new ObjectMapper(factory); + CatalogData data = mapper.readValue(catalog, CatalogData.class); + for (Attribute attr : data.getAttributes()) { + if (attr.isRequestContext()) { + requestContextAttributes.put(attr.getName(), attr); + } + attributeMap.put(attr.getName(), attr); + } + Map<String, CatalogInfo> map = new HashMap<>(data.getEvents().size()); + for (Event event : data.getEvents()) { + CatalogInfo info = new CatalogInfo(); + info.event = event; + List<String> required = new ArrayList<>(); + List<String> names = new ArrayList<>(); + info.attributes = new HashMap<>(names.size()); + if (event.getAttributes() != null) { + for (EventAttribute eventAttribute : event.getAttributes()) { + String name = eventAttribute.getName(); + Attribute attribute = attributeMap.get(name); + info.attributes.put(name, attribute); + if (name.indexOf('.') != -1) { + name = name.replaceAll("\\.", ""); + } + if (name.indexOf('/') != -1) { + name = name.replaceAll("/", ""); + } + if (attribute.isRequestContext()) { + if (attribute.isRequired()) { + if (name.startsWith(REQCTX)) { + name = name.substring(REQCTX.length()); + } + required.add(name); + } + } else { + names.add(name); + } + } + } + info.requiredContextAttributes = required; + info.attributeNames = names; + map.put(NamingUtils.getFieldName(event.getName()), info); + } + return map; + } + + private class CatalogInfo { + private Event event; + + private List<String> requiredContextAttributes; + + private List<String> attributeNames; + + private Map<String, Attribute> attributes; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Column.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Column.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Column.java new file mode 100644 index 0000000..a9f112f --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Column.java @@ -0,0 +1,102 @@ +/* + * 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.logging.log4j.audit.constant; + +/** + * The Class Column. + */ +public class Column { + + /** The Constant PREFIX. */ + public static final String REQCTX_PREFIX = "ReqCtx_"; + + /** The Constant ID. */ + public static final String ID = REQCTX_PREFIX + "id"; + + /** The Constant BCID. */ + public static final String BCID = REQCTX_PREFIX + "bcId"; + + /** The Constant GUID. */ + public static final String GUID = "guId"; + + /** The Constant USER_PRODUCT. */ + public static final String USER_PRODUCT = REQCTX_PREFIX + "userProduct"; + + /** The Constant IP_ADDRESS. */ + public static final String IP_ADDRESS = REQCTX_PREFIX + "ipAddress"; + + /** The Constant SESSION_ID. */ + public static final String SESSION_ID = REQCTX_PREFIX + "sessionId"; + + /** The Constant USER_ID. */ + public static final String USER_ID = REQCTX_PREFIX + "userId"; + + /** The Constant HOST_NAME. */ + public static final String HOST_NAME = REQCTX_PREFIX + "hostName"; + + /** The Constant TIMEZONE_OFFSET. */ + public static final String TIMEZONE_OFFSET = REQCTX_PREFIX + "tzOffset"; + + /** The Constant REGION. */ + public static final String REGION = REQCTX_PREFIX + "region"; + + /** The Constant CANONICAL_ID. */ + public static final String CANONICAL_ID = REQCTX_PREFIX + "canonicalId"; + + /** The Constant BC_INDEX. */ + public static final String BC_INDEX = REQCTX_PREFIX + "bcIndex"; + + /** The Constant OFFERING_ID. */ + public static final String OFFERING_ID = REQCTX_PREFIX + "offeringId"; + + /** The Constant APP_ID. */ + public static final String APP_ID = REQCTX_PREFIX + "appId"; + + public static final String LOGIN_ID = REQCTX_PREFIX + "loginId"; + + public static final String USER_AGENT = REQCTX_PREFIX + "userAgent"; + + /** The Constant TIME_STAMP. */ + public static final String TIME_STAMP = "timeStamp"; + + /** The Constant EVENT_TYPE. */ + public static final String EVENT_TYPE = "eventType"; + + /** The Constant MEMBER. */ + public static final String MEMBER = "member"; + + public static final String HOLDING_CO_ID = "holdingCoId"; + + /** The Constant EVENT_ID. */ + public static final String EVENT_ID = "eventId"; + + public static final String FEATURE_NAME = REQCTX_PREFIX + "featureName"; + + public static final String COMPLETION_STATUS = "completionStatus"; + + public static final String RAW_DATA = "rawData"; + + public static final String NONRC_IP_ADDRESS = "ipAddress"; + + public static final String NONRC_SESSION_ID = "sessionId"; + + public static final String NONRC_USER_AGENT = "userAgent"; + + public static final String APPLICATION_ID = "applicationId"; + + public static final String NONRC_USER_PRODUCT = "userProduct"; +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Environment.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Environment.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Environment.java new file mode 100644 index 0000000..dcbda6b --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/Environment.java @@ -0,0 +1,45 @@ +/* + * 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.logging.log4j.audit.constant; + +/** + * Various environments applications run in. + */ +public enum Environment { + + PROD("Production"), PRE_PROD("Pre-Production"), UAT("UserAcceptance"), BETA("Beta"), + RC("ReleaseCandidate"), STAGING("Staging"), + DEV("Development"), DEVQA("DevelopmentQA"), QA("QA"), PERF("Performance"); + private final String name; + + private Environment(String name) { + this.name = name; + } + + public String toString() { + return this.name; + } + + public static Environment getByName(String name) { + for (Environment region : values()) { + if (region.name.equals(name)) { + return region; + } + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/QueryParameter.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/QueryParameter.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/QueryParameter.java new file mode 100644 index 0000000..742345c --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/constant/QueryParameter.java @@ -0,0 +1,41 @@ +/* + * 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.logging.log4j.audit.constant; + +public class QueryParameter { + public static final String EVENT = "event"; + public static final String ATTRIBUTE = "attribute"; + public static final String ATTRIBUTE_DETAILS = "attributeDetails"; + public static final String CATEGORY = "category"; + + public static final String START_DATE = "startDate"; + public static final String END_DATE = "endDate"; + public static final String USER_TYPE = "userType"; + public static final String LIMIT = "limit"; + public static final String METHOD_NAME = "method"; + public static final String LATEST_FIRST = "latestFirst"; + public static final String START_KEY = "startKey"; + public static final String NEXT_GUID = "nextGuid"; + public static final String LAST_GUID = "lastGuid"; + public static final String COUNT_ONLY = "countOnly"; + public static final String PAGE_NUMBER = "pageNumber"; + public static final String BATCH_REQ_TOKEN = "batchReqToken"; + public static final String COUNT_REQUIRED = "countRequired"; + public static final String CLIENT_APP = "clientApp"; + public static final String EVENT_TYPE = "eventType"; + public static final String REGION = "region"; +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/dto/AuditDto.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/dto/AuditDto.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/dto/AuditDto.java new file mode 100644 index 0000000..ff6eea2 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/dto/AuditDto.java @@ -0,0 +1,87 @@ +/* + * 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.logging.log4j.audit.dto; + +import java.util.Map; + +/** + * Container for Audit Event data. + */ +public class AuditDto { + /** + * The name of the event. + */ + private String eventName; + + /** + * The RequestContext Map. + */ + private Map<String, String> requestContextMap; + + /** + * The event specific attributes. + */ + private Map<String, String> properties; + + /** + * Get the name of the event. + * @return the name of the event. + */ + public String getEventName() { + return eventName; + } + + /** + * Set the name of the event. + * @param eventName The name of the event. + */ + public void setEventName(String eventName) { + this.eventName = eventName; + } + + /** + * Returns the RequestContext data map. + * @return A Map containing all the RequestContext keys and values. + */ + public Map<String, String> getRequestContextMap() { + return requestContextMap; + } + + /** + * Set the RequstContext Map. + * @param requestContextMap the RequestContext Map. + */ + public void setRequestContextMap(Map<String, String> requestContextMap) { + this.requestContextMap = requestContextMap; + } + + /** + * Gets the Map of properties for this event. + * @return the Map of event properties. + */ + public Map<String, String> getProperties() { + return properties; + } + + /** + * Sets the RequestContext properties. + * @param properties The RequestContext properties. + */ + public void setProperties(Map<String, String> properties) { + this.properties = properties; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/exception/AuditException.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/exception/AuditException.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/exception/AuditException.java new file mode 100644 index 0000000..7663a09 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/exception/AuditException.java @@ -0,0 +1,37 @@ +/* + * 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.logging.log4j.audit.exception; + +/** + * + */ +public class AuditException extends RuntimeException { + + private static final long serialVersionUID = -5254085965679589585L; + + public AuditException(String message) { + super(message); + } + + public AuditException(Throwable e) { + super(e); + } + + public AuditException(String message, Throwable e) { + super(message, e); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/AccessorDefinition.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/AccessorDefinition.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/AccessorDefinition.java new file mode 100644 index 0000000..cf812ae --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/AccessorDefinition.java @@ -0,0 +1,153 @@ +/* + * 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.logging.log4j.audit.generator; + +import org.apache.logging.log4j.audit.util.NamingUtils; +import org.apache.logging.log4j.audit.util.StringUtil; + +public class AccessorDefinition { + + public class StandardGetter extends MethodDefinition { + public StandardGetter(AccessorDefinition beanDefinition) { + super(beanDefinition.getType(), NamingUtils.getAccessorName( + beanDefinition.getType(), beanDefinition.getName())); + if (getterContent != null) { + setContent("\t" + StringUtil.filterContent(getterContent, name, type)); + } else { + StringBuilder sb = new StringBuilder(); + sb.append("\treturn ").append(beanDefinition.getName()).append(";"); + setContent(sb.toString()); + } + } + } + + public class StandardSetter extends MethodDefinition { + public StandardSetter(AccessorDefinition beanDefinition) { + super(beanDefinition.getType(), NamingUtils + .getMutatorName(beanDefinition.getName())); + setReturnType("void"); + if (setterContent != null) { + setContent("\t" + + StringUtil.filterContent(setterContent, name, type)); + } else { + StringBuilder sb = new StringBuilder(); + sb.append("\tthis.").append(beanDefinition.getName()) + .append(" = ").append(beanDefinition.getName()).append(";"); + setContent(sb.toString()); + } + getParameters().add(new Parameter(beanDefinition.getName(), beanDefinition.getType(), "")); + } + } + + public static String variableCaseName(String variable) { + return variable.substring(0, 1).toLowerCase() + variable.substring(1); + } + + private String name; + private String type; + private String packageName = null; + + private String annotation = null; + + private String setterContent; + private String getterContent; + + public void setSetterContent(String setterContent) { + this.setterContent = setterContent; + } + + public void setGetterContent(String getterContent) { + this.getterContent = getterContent; + } + + public AccessorDefinition(String name, String type) { + this(name, type, null, null); + } + + public AccessorDefinition(String name, String type, String setterContent, String getterContent) { + + setName(NamingUtils.getFieldName(name)); + setType(type); + setSetterContent(setterContent); + setGetterContent(getterContent); + } + + public void addBean(ClassGenerator generator) { + addBean(generator, true, true, true); + } + + public void addBean(ClassGenerator generator, boolean addLocalVariable, boolean addGetter, boolean addSetter) { + + if (generator.isClass() && addLocalVariable) { + generator.addLocalVariable(new VariableDefinition("private", + getType(), getName(), null, getAnnotation())); + } + + if (packageName != null) { + generator.getImports().add(packageName); + } + if (addGetter) { + MethodDefinition methodDefinition = new StandardGetter(this); + methodDefinition.setInterface(!generator.isClass()); + generator.addBeanMethods(this); + generator.addMethod(methodDefinition); + } + if (addSetter) { + MethodDefinition methodDefinition = new StandardSetter(this); + methodDefinition.setInterface(!generator.isClass()); + generator.addMethod(methodDefinition); + } + } + + private String extractPackageName(String variable) { + int lastDot = variable.lastIndexOf('.'); + if (lastDot < 0) { + return null; + } + return variable; + } + + public String getAnnotation() { + return annotation; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public void setAnnotation(String annotation) { + this.annotation = annotation; + } + + public void setName(String name) { + this.name = variableCaseName(name); + } + + public void setType(String type) { + this.packageName = extractPackageName(type); + int lastDot = type.lastIndexOf('.'); + this.type = type; + if (lastDot >= 0) { + this.type = type.substring(lastDot + 1); + } + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ClassGenerator.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ClassGenerator.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ClassGenerator.java new file mode 100644 index 0000000..31a3bf4 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ClassGenerator.java @@ -0,0 +1,355 @@ +/* + * 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.logging.log4j.audit.generator; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.logging.log4j.audit.util.NamingUtils; + +import static org.apache.logging.log4j.audit.generator.Constants.*; + +/** + * Generates the Classes and Interfaces for Audit Logging based on data in the Catalog. + */ +public final class ClassGenerator { + + protected List<AccessorDefinition> beanMethods = new ArrayList<AccessorDefinition>(); + private boolean isClass = true; + private String className; + private String parentClassName; + private String packageName; + private String baseFolder; + private String javadocComment; + private List<String> implementsDeclarations = new ArrayList<>(); + + private Set<String> importsDeclarations = new HashSet<String>(); + + private List<VariableDefinition> localVariables = new ArrayList<>(); + + private List<ConstructorDefinition> constructors = new ArrayList<>(); + + private List<MethodDefinition> methods = new ArrayList<>(); + + private boolean runPrewrite = false; + + private boolean isAbstract = false; + + private String visability = PUBLIC; + + private String annotations = null; + + private String code = null; + + private String typeStatement = null; + + public ClassGenerator(String className, String baseFolder) { + this.className = className; + this.baseFolder = baseFolder; + } + + public String getTypeStatement() { + return typeStatement; + } + + public void setTypeStatement(String typeStatement) { + this.typeStatement = typeStatement; + } + + /** + * Code is not resolved and is just injected straight into the main code + * block of the respective class + * + * @return + */ + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public void addBeanMethods(AccessorDefinition beanDefinition) { + beanMethods.add(beanDefinition); + } + + public void addConstructor(ConstructorDefinition constructorDefinition) { + constructors.add(constructorDefinition); + } + + public void addLocalVariable(VariableDefinition definition) { + localVariables.add(definition); + } + + public void addMethod(MethodDefinition definition) { + methods.add(definition); + } + + public void addSingelton(String name, List<String> parameters) { + if (Character.isUpperCase(name.charAt(0))) { + name = name.substring(0, 1).toLowerCase() + name.substring(1); + } + + VariableDefinition definition = new VariableDefinition("private", + getClassName(), name, null); + definition.setMakeStatic(true); + addLocalVariable(definition); + addMethod(MethodDefinition.getStandardSingleton(getClassName(), name, parameters)); + } + + public String getAnnotations() { + return annotations; + } + + public void setAnnotations(String annotations) { + this.annotations = annotations; + } + + public List<AccessorDefinition> getBeanMethods() { + return beanMethods; + } + + public String getClassName() { + return className; + } + + public String getParentClassName() { + return parentClassName; + } + + public void setParentClassName(String parentClassName) { + this.parentClassName = parentClassName; + } + + public List<String> getImplements() { + return implementsDeclarations; + } + + public Set<String> getImports() { + return importsDeclarations; + } + + public List<MethodDefinition> getMethodDefinitions() { + return methods; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public List<VariableDefinition> getVariableDefinitions() { + return localVariables; + } + + public String getVisability() { + return visability; + } + + public void setVisability(String visability) { + this.visability = visability; + } + + public boolean isAbstract() { + return isAbstract; + } + + public void setAbstract(boolean isAbstract) { + this.isAbstract = isAbstract; + } + + public boolean isClass() { + return isClass; + } + + public void setClass(boolean isClass) { + this.isClass = isClass; + } + + /** + * Override this method it gets called once before toString do if toString + * gets called 5 time this will only be called on the first + */ + public void preWrite() { + + } + + public void generate() throws Exception { + StringBuilder sb = new StringBuilder(baseFolder); + if (getPackageName() != null) { + sb.append("/").append(getPackageName().replaceAll("\\.", "/")); + } + sb.append("/").append(NamingUtils.upperFirst(getClassName())) + .append(".java"); + String fullPath = sb.toString(); + System.out.println(fullPath); + File file = new File(fullPath); + DataOutputStream out = new DataOutputStream(openOutputStream(file)); + out.writeBytes(getClassContents()); + out.close(); + + } + + public String getClassContents() throws Exception { + if (getClassName() == null) { + throw new Exception("Class name has to be set"); + } + + if (!runPrewrite) { + preWrite(); + runPrewrite = true; + } + + StringBuilder sb = new StringBuilder(); + sb.append("package ").append(getPackageName()).append(";\n\n"); + if (getImports() != null) { + List<String> list = new ArrayList<String>(getImports()); + Collections.sort(list); + for (String element : list) { + sb.append("import ").append(element).append(";\n"); + } + sb.append("\n"); + } + + sb.append("/**\n"); + if (getJavadocComment() != null) { + sb.append(" * ").append(getJavadocComment()); + } + sb.append("\n * @author generated"); + sb.append("\n */\n"); + + if (annotations != null) { + sb.append(annotations); + sb.append("\n"); + } + + sb.append(getVisability()); + if (isClass()) { + sb.append(" class "); + } else { + sb.append(" interface "); + } + sb.append(getClassName()); + if (typeStatement != null) { + sb.append(" <").append(typeStatement).append("> "); + } + + if (getParentClassName() != null && getParentClassName().length() > 0) { + sb.append(" extends ").append(getParentClassName()); + } + if (getImplements() != null && getImplements().size() > 0) { + sb.append(" implements "); + boolean first = true; + for (String element : getImplements()) { + if (!first) { + sb.append(", "); + } + sb.append(element); + first = false; + } + } + sb.append(" {\n\n"); + if (localVariables != null) { + Collections.sort(localVariables); + for (VariableDefinition element : localVariables) { + sb.append(element).append("\n"); + } + } + + if (constructors != null) { + Collections.sort(constructors); + for (ConstructorDefinition element : constructors) { + sb.append(element).append("\n\n"); + } + } + + if (beanMethods.size() > 0 && isClass()) { + MethodDefinition definition = new MethodDefinition("String", + "toString"); + StringBuilder buffer = new StringBuilder(); + buffer.append("\tStringBuilder sb = new StringBuilder();"); + buffer.append("\n\tsb.append(super.toString());"); + for (AccessorDefinition element : beanMethods) { + buffer.append("\n\tsb.append(\", "); + buffer.append(element.getName()) + .append("=\").append(") + .append(NamingUtils.getAccessorName(element.getName(), + element.getType())).append("());"); + } + buffer.append("\n\treturn sb.toString();"); + definition.setContent(buffer.toString()); + methods.add(definition); + } + + if (methods != null) { + Collections.sort(methods); + for (MethodDefinition element : methods) { + sb.append(element).append("\n\n"); + } + } + + if (code != null) { + sb.append(code).append("\n"); + } + + sb.append("}"); + return sb.toString(); + } + + public String getJavadocComment() { + return javadocComment; + } + + public void setJavadocComment(String javadocComment) { + this.javadocComment = javadocComment; + } + + private OutputStream openOutputStream(File file) throws IOException { + if (file.exists()) { + if (file.isDirectory()) { + throw new IOException("File '" + file + "' exists but is a directory"); + } + if (!file.canWrite()) { + throw new IOException("File '" + file + "' cannot be written to"); + } + } else { + final File parent = file.getParentFile(); + if (parent != null) { + if (!parent.mkdirs() && !parent.isDirectory()) { + throw new IOException("Directory '" + parent + "' could not be created"); + } + } + } + return new FileOutputStream(file, false); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Constants.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Constants.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Constants.java new file mode 100644 index 0000000..fb129bb --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Constants.java @@ -0,0 +1,25 @@ +/* + * 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.logging.log4j.audit.generator; + +/** + * + */ +public class Constants { + + public static final String PUBLIC = "public"; +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ConstructorDefinition.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ConstructorDefinition.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ConstructorDefinition.java new file mode 100644 index 0000000..b9989cb --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/ConstructorDefinition.java @@ -0,0 +1,122 @@ +/* + * 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.logging.log4j.audit.generator; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.apache.logging.log4j.audit.generator.Constants.*; + +public class ConstructorDefinition implements Comparable<ConstructorDefinition> { + private String visability = PUBLIC; + + private String name; + + private List<Parameter> parameters = new ArrayList<>(); + + private List<String> exceptions = new ArrayList<>(); + + private String content; + + public ConstructorDefinition(String className) { + this.name = className; + } + + public String getContent() { + return content; + } + + public List<String> getExceptions() { + return exceptions; + } + + public String getName() { + return name; + } + + public List<Parameter> getParameters() { + return parameters; + } + + public String getVisability() { + return visability; + } + + public void setContent(String content) { + this.content = content; + } + + public void setExceptions(List<String> exceptions) { + this.exceptions = exceptions; + } + + public void setName(String name) { + this.name = name; + } + + public void setParameters(List<Parameter> parameters) { + this.parameters = parameters; + } + + public void setVisability(String visability) { + this.visability = visability; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getVisability()).append(" "); + sb.append(getName()).append("("); + if (getParameters() != null) { + boolean first = true; + for (Iterator<Parameter> iter = getParameters().iterator(); iter + .hasNext(); ) { + Parameter element = iter.next(); + if (!first) { + sb.append(", "); + } + sb.append(element); + first = false; + } + } + sb.append(")"); + if (getExceptions() != null && getExceptions().size() > 0) { + sb.append(" throws "); + boolean first = true; + for (Iterator<String> iter = getExceptions().iterator(); iter + .hasNext(); ) { + String element = iter.next(); + if (!first) { + sb.append(", "); + } + sb.append(element); + first = false; + } + } + + sb.append(" {\n"); + sb.append(getContent()); + sb.append("\n}\n\n"); + return sb.toString(); + } + + @Override + public int compareTo(ConstructorDefinition arg0) { + return getParameters().size() - arg0.getParameters().size(); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/InterfacesGenerator.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/InterfacesGenerator.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/InterfacesGenerator.java new file mode 100644 index 0000000..9df7406 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/InterfacesGenerator.java @@ -0,0 +1,335 @@ +/* + * 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.logging.log4j.audit.generator; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.audit.util.NamingUtils; +import org.apache.logging.log4j.catalog.api.Attribute; +import org.apache.logging.log4j.catalog.api.CatalogData; +import org.apache.logging.log4j.catalog.api.CatalogReader; +import org.apache.logging.log4j.catalog.api.Constraint; +import org.apache.logging.log4j.catalog.api.ConstraintType; +import org.apache.logging.log4j.catalog.api.Event; +import org.apache.logging.log4j.catalog.api.EventAttribute; +import org.apache.logging.log4j.catalog.api.dao.CatalogDao; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.context.support.FileSystemXmlApplicationContext; +import org.springframework.core.env.CommandLinePropertySource; +import org.springframework.core.env.JOptCommandLinePropertySource; +import org.springframework.stereotype.Component; + +@Component +public class InterfacesGenerator { + + private static final Logger LOGGER = LogManager.getLogger(InterfacesGenerator.class); + + private static final String CONSTRAINT_IMPORT = "org.apache.logging.log4j.audit.annotation.Constraint"; + private static final String REQUIRED_IMPORT = "org.apache.logging.log4j.audit.annotation.Required"; + private static final String CONSTRAINTS_ATTR = ", constraints={"; + private static final String CONSTRAINT = "@Constraint(constraintType=\"%s\", constraintValue=\"%s\")"; + private static final String KEY = "key=\""; + private static final String REQUIRED_ATTR = "required=true"; + private static final String REQUIRED = "@Required"; + + private static final String REQUEST_CONTEXT_IMPORT = "org.apache.logging.log4j.audit.annotation.RequestContext"; + private static final String PARENT_IMPORT = "org.apache.logging.log4j.audit.AuditEvent"; + private static final String MAX_LENGTH_IMPORT = "org.apache.logging.log4j.audit.annotation.MaxLength"; + private static final String REQCTX_ANN = "@RequestContext("; + + private static final String PARENT_CLASS = "AuditEvent"; + + private static final String REQCTX = "ReqCtx_"; + + private static final String EVENT_ID = "eventID"; + + private static final String EVENT_TYPE = "eventType"; + + private static final String TIMESTAMP = "timeStamp"; + + private static final String CONTEXT = "context"; + + @Autowired + private CatalogReader catalogReader; + + @Value("${packageName:org.apache.logging.log4j.audit.event}") + private String packageName; + + @Value("${outputDirectory:target/generated-sources/log4j-audit}") + private String outputDirectory; + + @Value("${maxKeyLength:32}") + private int maxKeyLength; + + @Value("${enterpriseId:18060}") + private int enterpriseId; + + public CatalogReader getCatalogReader() { + return catalogReader; + } + + public void setCatalogReader(CatalogReader catalogReader) { + this.catalogReader = catalogReader; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public String getOutputDirectory() { + return outputDirectory; + } + + public void setOutputDirectory(String outputDirectory) { + this.outputDirectory = outputDirectory; + } + + public void setMaxKeyLength(int maxKeyLength) { + this.maxKeyLength = maxKeyLength; + } + + public void setEnterpriseId(int enterpriseId) { + this.enterpriseId = enterpriseId; + } + + /** + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + OptionParser parser = new OptionParser(); + parser.accepts(CONTEXT); + OptionSet options = parser.parse(args); + CommandLinePropertySource<joptsimple.OptionSet> clps = new JOptCommandLinePropertySource(options); + ApplicationContext applicationContext = null; + if (clps.containsProperty(CONTEXT)) { + applicationContext = new FileSystemXmlApplicationContext(clps.getProperty(CONTEXT)); + } else { + applicationContext = new ClassPathXmlApplicationContext(); + } + InterfacesGenerator generator = + (InterfacesGenerator) applicationContext.getBean("org.apache.logging.log4j.audit.generator.InterfacesGenerator"); + if (generator != null) { + generator.generateSource(); + return; + } + LOGGER.error("Unable to generate source files, no generator is configured"); + System.exit(-1); + } + + public void generateSource() throws Exception { + boolean errors = false; + CatalogData catalogData = catalogReader.read(); + if (catalogData != null) { + List<Event> events = catalogData.getEvents(); + Map<String, Attribute> requestContextAttrs = new HashMap<>(); + Map<String, Boolean> requestContextIsRequired = new HashMap<>(); + Map<String, Attribute> attributes = catalogReader.getAttributes(); + Map<String, String> importedTypes = new HashMap<>(); + boolean anyConstraints = false; + for (Attribute attribute : attributes.values()) { + if (attribute.isRequestContext()) { + String name = attribute.getName(); + if (name.startsWith(REQCTX)) { + name = name.substring(REQCTX.length()); + } + requestContextAttrs.put(name, attribute); + requestContextIsRequired.put(name, attribute.isRequired()); + } + } + for (Event event : events) { + String maxLen = Integer.toString(enterpriseId); + int maxNameLength = maxKeyLength - maxLen.length() - 1; + if (event.getName().length() > maxNameLength) { + LOGGER.error("{} exceeds maximum length of {} for an event name", event.getName(), maxNameLength); + errors = true; + continue; + } + ClassGenerator classGenerator = new ClassGenerator( + NamingUtils.getClassName(event.getName()), outputDirectory); + classGenerator.setClass(false); + classGenerator.setPackageName(packageName); + classGenerator.setParentClassName(PARENT_CLASS); + classGenerator.setJavadocComment(event.getDescription()); + Set<String> imports = classGenerator.getImports(); + imports.add(PARENT_IMPORT); + StringBuilder annotations = new StringBuilder(); + imports.add(MAX_LENGTH_IMPORT); + annotations.append("@MaxLength(").append(maxKeyLength).append(")"); + + List<EventAttribute> eventAttributes = event.getAttributes(); + boolean anyRequired = false; + if (eventAttributes != null) { + for (EventAttribute eventAttribute : eventAttributes) { + Attribute attribute = attributes.get(eventAttribute.getName()); + if (attribute == null) { + LOGGER.error("Unable to locate attribute name {}", eventAttribute.getName()); + errors = true; + continue; + } + if (attribute.isRequestContext() && attribute.isRequired()) { + String name = eventAttribute.getName(); + if (name.startsWith(REQCTX)) { + name = name.substring(REQCTX.length()); + } + requestContextIsRequired.put(name, Boolean.TRUE); + continue; + } + String name = attribute.getName(); + + if (EVENT_ID.equals(name) || EVENT_TYPE.equals(name) || TIMESTAMP.equals(name)) { + continue; + } + + if (name.indexOf('.') != -1) { + name = name.replaceAll("\\.", ""); + } + + if (name.indexOf('/') != -1) { + name = name.replaceAll("/", ""); + } + if (name.length() > maxKeyLength) { + LOGGER.error("{} exceeds maximum length of {} for an attribute name", name, maxKeyLength); + errors = true; + continue; + } + + String type = attribute.getDataType().getTypeName(); + + MethodDefinition definition = new MethodDefinition("void", + NamingUtils.getMutatorName(name)); + if (!attribute.isRequestContext() && attribute.getDataType().getImportClass() != null) { + if (!importedTypes.containsKey(attribute.getDataType().getTypeName())) { + importedTypes.put(attribute.getDataType().getTypeName(), attribute.getDataType().getImportClass()); + } + } + definition.addParameter(new Parameter(name, type, attribute.getDescription())); + definition.setInterface(true); + definition.setVisability("public"); + definition.setJavadocComments(attribute.getDisplayName() + + " : " + attribute.getDescription()); + + StringBuilder buffer = new StringBuilder(); + Set<Constraint> constraints = attribute.getConstraints(); + boolean first = true; + if (attribute.isRequired() || eventAttribute.isRequired()) { + anyRequired = true; + buffer.append(REQUIRED); + first = false; + } + if (constraints != null && constraints.size() > 0) { + anyConstraints = true; + for (Constraint constraint : constraints) { + if (!first) { + buffer.append("\n "); + } + first = false; + appendConstraint(constraint, buffer); + } + } + if (buffer.length() > 0) { + definition.setAnnotation(buffer.toString()); + } + classGenerator.addMethod(definition); + + } + } + if (importedTypes.size() > 0) { + for (String className : importedTypes.values()) { + imports.add(className); + } + } + if (anyRequired) { + imports.add(REQUIRED_IMPORT); + } + boolean firstReqCtx = true; + if (requestContextAttrs.size() > 0) { + imports.add(REQUEST_CONTEXT_IMPORT); + StringBuilder reqCtx = new StringBuilder(); + for (Map.Entry<String, Attribute> entry : requestContextAttrs.entrySet()) { + if (!firstReqCtx) { + reqCtx.append(")\n"); + } + firstReqCtx = false; + reqCtx.append(REQCTX_ANN); + reqCtx.append(KEY).append(entry.getKey()).append("\""); + Attribute attrib = entry.getValue(); + String name = attrib.getName(); + if (name.startsWith(REQCTX)) { + name = name.substring(REQCTX.length()); + } + if (requestContextIsRequired.get(name)) { + reqCtx.append(", ").append(REQUIRED_ATTR); + } + Set<Constraint> constraints = entry.getValue().getConstraints(); + if (constraints != null && constraints.size() > 0) { + anyConstraints = true; + reqCtx.append(CONSTRAINTS_ATTR); + boolean first = true; + for (Constraint constraint : constraints) { + if (!first) { + reqCtx.append(", "); + } + first = false; + appendConstraint(constraint, reqCtx); + } + reqCtx.append("}"); + + } + } + reqCtx.append(")"); + if (annotations.length() > 0) { + annotations.append("\n"); + } + annotations.append(reqCtx.toString()); + } + if (anyConstraints) { + imports.add(CONSTRAINT_IMPORT); + } + if (annotations.length() > 0) { + classGenerator.setAnnotations(annotations.toString()); + } + classGenerator.generate(); + } + } + if (errors) { + throw new IllegalStateException("Errors were encountered during code generation"); + } + } + + void appendConstraint(Constraint constraint, StringBuilder buffer) { + ConstraintType type = constraint.getConstraintType(); + // Add the escapes since they have been removed when converting the original data to a Java Strinng. They need to + // be added back for use in the Constraint declaration. + buffer.append(String.format(CONSTRAINT, type.getName(), constraint.getValue().replace("\\", "\\\\"))); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/MethodDefinition.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/MethodDefinition.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/MethodDefinition.java new file mode 100644 index 0000000..0d8f0b3 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/MethodDefinition.java @@ -0,0 +1,334 @@ +/* + * 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.logging.log4j.audit.generator; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.logging.log4j.audit.util.NamingUtils; +import org.apache.logging.log4j.audit.util.StringUtil; +import static org.apache.logging.log4j.audit.generator.Constants.PUBLIC; + +public class MethodDefinition implements Comparable<MethodDefinition> { + + private String visibility = PUBLIC; + + private String name; + + private String returnType; + + private String annotation = null; + + private boolean isStatic = false; + + private boolean isFinal = false; + + private boolean isAbstract = false; + + private boolean isInterface = false; + + private List<Parameter> parameters = new ArrayList<>(); + + private List<String> exceptions = new ArrayList<>(); + + private String content; + + private String javadocComments = null; + + public class StandardSingleton extends MethodDefinition { + /** + * this must be used with the local variable + */ + public StandardSingleton(String returnType, String name, List<String> parameters) { + super(returnType, name); + setStatic(true); + String prefix = "get"; + setName(prefix + name.substring(0, 1).toUpperCase() + + name.substring(1)); + StringBuilder sb = new StringBuilder(); + sb.append("\tif (").append(name).append(" == null) {\n"); + sb.append("\t\t").append(name).append(" = new ").append(returnType) + .append("("); + boolean first = true; + if (parameters != null) { + for (Iterator<String> iter = parameters.iterator(); iter.hasNext(); ) { + String element = iter.next(); + if (!first) { + sb.append(", "); + } + sb.append(element); + first = false; + } + } + sb.append(");\n\t}\n\treturn ").append(name).append(";"); + setContent(sb.toString()); + } + } + + private static MethodDefinition definition = new MethodDefinition("dumb", + "dumb"); + + public static MethodDefinition getStandardSingleton(String returnType, + String name, List<String> parameters) { + return definition.new StandardSingleton(returnType, name, parameters); + } + + public MethodDefinition(String returnType, String name, String content) { + this.returnType = returnType; + this.name = name; + if (content != null) { + this.content = StringUtil.filterContent(content, name, returnType); + } else { + createStubContent(); + } + } + + public MethodDefinition(String returnType, String name) { + this(returnType, name, null); + } + + private void createStubContent() { + String content = "// default stub - please modify\n"; + setContent(content); + if (!returnType.equals("void")) { + + if (returnType.equals("int")) { + setContent(content + "return 0;"); + } else if (returnType.equals("boolean")) { + setContent(content + "return false;"); + } else if (returnType.equals("double")) { + setContent(content + "return 0.0;"); + } else if (returnType.equals("long")) { + setContent(content + "return 0;"); + } else if (returnType.equals("float")) { + setContent(content + "return 0.0;"); + } else if (returnType.equals("float")) { + setContent(content + "return 0.0;"); + } else if (returnType.equals("char")) { + setContent(content + "return ' ';"); + } else if (returnType.equals("short")) { + setContent(content + "return 0;"); + } else { + setContent(content + "return null;"); + } + } + + } + + public MethodDefinition(Method method) { + this(method, null); + } + + public MethodDefinition(Method method, String content) { + this.returnType = method.getReturnType().getName(); + this.name = method.getName(); + + if (content == null) { + createStubContent(); + } else { + this.content = content; + } + int pName = 'a'; + for (Class<?> param : method.getParameterTypes()) { + addParameter(new Parameter(Character.toString((char) pName++), + param.getName(), "")); + } + + for (Class<?> param : method.getExceptionTypes()) { + exceptions.add(param.getName()); + } + } + + public void addParameter(Parameter paramater) { + parameters.add(paramater); + } + + public String getAnnotation() { + return annotation; + } + + public String getContent() { + return content; + } + + public List<String> getExceptions() { + return exceptions; + } + + public String getName() { + return name; + } + + public List<Parameter> getParameters() { + return parameters; + } + + public String getReturnType() { + return returnType; + } + + public String getVisability() { + return visibility; + } + + public boolean isAbstract() { + return isAbstract; + } + + public boolean isFinal() { + return isFinal; + } + + public boolean isInterface() { + return isInterface; + } + + public boolean isStatic() { + return isStatic; + } + + public void setAbstract(boolean isAbstract) { + this.isAbstract = isAbstract; + } + + public void setAnnotation(String annotation) { + this.annotation = annotation; + } + + public void setContent(String content) { + this.content = content; + } + + public void setExceptions(List<String> exceptions) { + this.exceptions = exceptions; + } + + public void setFinal(boolean isFinal) { + this.isFinal = isFinal; + } + + public void setInterface(boolean isInterface) { + this.isInterface = isInterface; + } + + public void setName(String name) { + this.name = name; + } + + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + public void setStatic(boolean isStatic) { + this.isStatic = isStatic; + } + + public void setVisability(String visability) { + this.visibility = visability; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(" /**\n"); + if (getJavadocComments() != null) { + sb.append(" * ").append(getJavadocComments()); + } + + if (getParameters() != null) { + for (Parameter param : getParameters()) { + sb.append("\n * @param ").append(param.getName()) + .append(" ").append(param.getDescription()); + } + } + + sb.append("\n */\n"); + sb.append(" "); + if (getAnnotation() != null) { + sb.append(getAnnotation()); + sb.append("\n "); + } + + if (getVisability() != null) { + sb.append(getVisability()).append(" "); + } + if (isFinal() && !isInterface()) { + sb.append("final "); + } + if (isStatic() && !isInterface()) { + sb.append("static "); + } + if (isAbstract() && !isInterface()) { + sb.append("abstract "); + } + sb.append(returnType).append(" "); + sb.append(getName()).append("("); + if (getParameters() != null) { + boolean first = true; + for (Parameter element : getParameters()) { + if (!first) { + sb.append(", "); + } + sb.append(element); + first = false; + } + } + sb.append(")"); + if (getExceptions() != null && getExceptions().size() > 0) { + sb.append(" throws "); + boolean first = true; + for (String element : getExceptions()) { + if (!first) { + sb.append(", "); + } + sb.append(element); + first = false; + } + } + + if (isAbstract() || isInterface()) { + sb.append(";"); + return sb.toString(); + } + sb.append(" {\n"); + sb.append(getContent()); + sb.append("\n}"); + return sb.toString(); + } + + @Override + public int compareTo(MethodDefinition arg0) { + int res = NamingUtils.getMethodShortName(getName()).compareTo( + NamingUtils.getMethodShortName(arg0.getName())); + if (res == 0) { + return getName().compareTo(arg0.getName()); + } + return res; + } + + public String getJavadocComments() { + return javadocComments; + } + + public void setJavadocComments(String javadocComments) { + this.javadocComments = javadocComments; + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Parameter.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Parameter.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Parameter.java new file mode 100644 index 0000000..0bd6c54 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/Parameter.java @@ -0,0 +1,77 @@ +/* + * 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.logging.log4j.audit.generator; + +public class Parameter { + + private boolean isFinal = false; + + private String name; + + private String type; + + private String description; + + public Parameter(String name, String type, String description) { + this.name = name; + this.type = type; + this.description = description; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public boolean isFinal() { + return isFinal; + } + + public void setFinal(boolean isFinal) { + this.isFinal = isFinal; + } + + public void setName(String name) { + this.name = name; + } + + public void setType(String type) { + this.type = type; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (isFinal()) { + sb.append("final "); + } + sb.append(type).append(" ").append(name); + return sb.toString(); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/VariableDefinition.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/VariableDefinition.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/VariableDefinition.java new file mode 100644 index 0000000..6a1a4e3 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/generator/VariableDefinition.java @@ -0,0 +1,149 @@ +/* + * 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.logging.log4j.audit.generator; + +public class VariableDefinition implements Comparable<VariableDefinition> { + private String visability; + private boolean makeStatic = false; + private boolean makeFinal = false; + private boolean createGetter = false; + private boolean createSetter = false; + private String type; + private String name; + private String initialValue; + private String annotation = null; + + public VariableDefinition(String visability, String type, String name, + String initialValue) { + this.visability = visability; + this.type = type; + this.name = name; + this.initialValue = initialValue; + } + + public VariableDefinition(String visability, String type, String name, + String initialValue, String annotation) { + this.visability = visability; + this.type = type; + this.name = name; + this.initialValue = initialValue; + this.annotation = annotation; + } + + public String getAnnotation() { + return annotation; + } + + public String getInitialValue() { + return initialValue; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public String getVisability() { + return visability; + } + + public boolean isCreateGetter() { + return createGetter; + } + + public boolean isCreateSetter() { + return createSetter; + } + + public boolean isMakeFinal() { + return makeFinal; + } + + public boolean isMakeStatic() { + return makeStatic; + } + + public void setAnnotation(String annotation) { + this.annotation = annotation; + } + + public void setCreateGetter(boolean createGetter) { + this.createGetter = createGetter; + } + + public void setCreateSetter(boolean createSetter) { + this.createSetter = createSetter; + } + + public void setInitialValue(String initialValue) { + this.initialValue = initialValue; + } + + public void setMakeFinal(boolean makeFinal) { + this.makeFinal = makeFinal; + } + + public void setMakeStatic(boolean makeStatic) { + this.makeStatic = makeStatic; + } + + public void setName(String name) { + this.name = name; + } + + public void setType(String type) { + this.type = type; + } + + public void setVisability(String visability) { + this.visability = visability; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (getAnnotation() != null) { + sb.append(getAnnotation()); + sb.append("\n"); + } + + sb.append(visability).append(" "); + if (isMakeStatic()) { + sb.append("static "); + } + if (isMakeFinal()) { + sb.append("final "); + } + sb.append(type).append(" ").append(name); + if (initialValue != null && initialValue.length() > 0) { + sb.append(" = ").append(initialValue); + } + sb.append(";"); + + // todo create getters and setters + + return sb.toString(); + } + + @Override + public int compareTo(VariableDefinition arg0) { + return getName().compareTo(arg0.getName()); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j-audit/blob/f0884aeb/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/layout/AuditLayout.java ---------------------------------------------------------------------- diff --git a/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/layout/AuditLayout.java b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/layout/AuditLayout.java new file mode 100644 index 0000000..e704c30 --- /dev/null +++ b/log4j-audit/log4j-audit-api/src/main/java/org/apache/logging/log4j/audit/layout/AuditLayout.java @@ -0,0 +1,20 @@ +/* + * 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.logging.log4j.audit.layout; + +public class AuditLayout { +}
