This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
/*
* 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.tomcat.util.modeler;
import javax.management.MBeanAttributeInfo;
/**
* <p>Internal configuration information for an <code>Attribute</code>
* descriptor.</p>
*
* @author Craig R. McClanahan
*/
public class AttributeInfo extends FeatureInfo {
static final long serialVersionUID = -2511626862303972143L;
// ----------------------------------------------------- Instance Variables
protected String displayName = null;
// Information about the method to use
protected String getMethod = null;
protected String setMethod = null;
protected boolean readable = true;
protected boolean writeable = true;
protected boolean is = false;
// ------------------------------------------------------------- Properties
/**
* @return the display name of this attribute.
*/
public String getDisplayName() {
return this.displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
/**
* @return the name of the property getter method, if non-standard.
*/
public String getGetMethod() {
if(getMethod == null)
getMethod = getMethodName(getName(), true, isIs());
return this.getMethod;
}
public void setGetMethod(String getMethod) {
this.getMethod = getMethod;
}
/**
* Is this a boolean attribute with an "is" getter?
* @return <code>true</code> if this is a boolean attribute
* with an "is" getter
*/
public boolean isIs() {
return this.is;
}
public void setIs(boolean is) {
this.is = is;
}
/**
* Is this attribute readable by management applications?
* @return <code>true</code> if readable
*/
public boolean isReadable() {
return this.readable;
}
public void setReadable(boolean readable) {
this.readable = readable;
}
/**
* @return the name of the property setter method, if non-standard.
*/
public String getSetMethod() {
if( setMethod == null )
setMethod = getMethodName(getName(), false, false);
return this.setMethod;
}
public void setSetMethod(String setMethod) {
this.setMethod = setMethod;
}
/**
* Is this attribute writable by management applications?
* @return <code>true</code> if writable
*/
public boolean isWriteable() {
return this.writeable;
}
public void setWriteable(boolean writeable) {
this.writeable = writeable;
}
// --------------------------------------------------------- Public Methods
/**
* Create and return a <code>ModelMBeanAttributeInfo</code> object that
* corresponds to the attribute described by this instance.
* @return the attribute info
*/
MBeanAttributeInfo createAttributeInfo() {
// Return our cached information (if any)
if (info == null) {
info = new MBeanAttributeInfo(getName(), getType(), getDescription(),
isReadable(), isWriteable(), false);
}
return (MBeanAttributeInfo)info;
}
// -------------------------------------------------------- Private Methods
/**
* Create and return the name of a default property getter or setter
* method, according to the specified values.
*
* @param name Name of the property itself
* @param getter Do we want a get method (versus a set method)?
* @param is If returning a getter, do we want the "is" form?
* @return the method name
*/
private String getMethodName(String name, boolean getter, boolean is) {
StringBuilder sb = new StringBuilder();
if (getter) {
if (is)
sb.append("is");
else
sb.append("get");
} else
sb.append("set");
sb.append(Character.toUpperCase(name.charAt(0)));
sb.append(name.substring(1));
return sb.toString();
}
}

View File

@@ -0,0 +1,160 @@
/*
* 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.tomcat.util.modeler;
import java.util.HashSet;
import javax.management.AttributeChangeNotification;
import javax.management.Notification;
import javax.management.NotificationFilter;
/**
* <p>Implementation of <code>NotificationFilter</code> for attribute change
* notifications. This class is used by <code>BaseModelMBean</code> to
* construct attribute change notification event filters when a filter is not
* supplied by the application.</p>
*
* @author Craig R. McClanahan
*/
public class BaseAttributeFilter implements NotificationFilter {
private static final long serialVersionUID = 1L;
// ----------------------------------------------------------- Constructors
/**
* Construct a new filter that accepts only the specified attribute
* name.
*
* @param name Name of the attribute to be accepted by this filter, or
* <code>null</code> to accept all attribute names
*/
public BaseAttributeFilter(String name) {
super();
if (name != null)
addAttribute(name);
}
// ----------------------------------------------------- Instance Variables
/**
* The set of attribute names that are accepted by this filter. If this
* list is empty, all attribute names are accepted.
*/
private HashSet<String> names = new HashSet<>();
// --------------------------------------------------------- Public Methods
/**
* Add a new attribute name to the set of names accepted by this filter.
*
* @param name Name of the attribute to be accepted
*/
public void addAttribute(String name) {
synchronized (names) {
names.add(name);
}
}
/**
* Clear all accepted names from this filter, so that it will accept
* all attribute names.
*/
public void clear() {
synchronized (names) {
names.clear();
}
}
/**
* Return the set of names that are accepted by this filter. If this
* filter accepts all attribute names, a zero length array will be
* returned.
* @return the array of names
*/
public String[] getNames() {
synchronized (names) {
return names.toArray(new String[names.size()]);
}
}
/**
* <p>Test whether notification enabled for this event.
* Return true if:</p>
* <ul>
* <li>This is an attribute change notification</li>
* <li>Either the set of accepted names is empty (implying that all
* attribute names are of interest) or the set of accepted names
* includes the name of the attribute in this notification</li>
* </ul>
*/
@Override
public boolean isNotificationEnabled(Notification notification) {
if (notification == null)
return false;
if (!(notification instanceof AttributeChangeNotification))
return false;
AttributeChangeNotification acn =
(AttributeChangeNotification) notification;
if (!AttributeChangeNotification.ATTRIBUTE_CHANGE.equals(acn.getType()))
return false;
synchronized (names) {
if (names.size() < 1)
return true;
else
return names.contains(acn.getAttributeName());
}
}
/**
* Remove an attribute name from the set of names accepted by this
* filter.
*
* @param name Name of the attribute to be removed
*/
public void removeAttribute(String name) {
synchronized (names) {
names.remove(name);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,192 @@
/*
* 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.tomcat.util.modeler;
import java.util.ArrayList;
import java.util.Iterator;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
/**
* <p>Implementation of <code>NotificationBroadcaster</code> for attribute
* change notifications. This class is used by <code>BaseModelMBean</code> to
* handle notifications of attribute change events to interested listeners.
*</p>
*
* @author Craig R. McClanahan
* @author Costin Manolache
*/
public class BaseNotificationBroadcaster implements NotificationBroadcaster {
// ----------------------------------------------------------- Constructors
// ----------------------------------------------------- Instance Variables
/**
* The set of registered <code>BaseNotificationBroadcasterEntry</code>
* entries.
*/
protected ArrayList<BaseNotificationBroadcasterEntry> entries =
new ArrayList<>();
// --------------------------------------------------------- Public Methods
/**
* Add a notification event listener to this MBean.
*
* @param listener Listener that will receive event notifications
* @param filter Filter object used to filter event notifications
* actually delivered, or <code>null</code> for no filtering
* @param handback Handback object to be sent along with event
* notifications
*
* @exception IllegalArgumentException if the listener parameter is null
*/
@Override
public void addNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback)
throws IllegalArgumentException {
synchronized (entries) {
// Optimization to coalesce attribute name filters
if (filter instanceof BaseAttributeFilter) {
BaseAttributeFilter newFilter = (BaseAttributeFilter) filter;
for (BaseNotificationBroadcasterEntry item : entries) {
if ((item.listener == listener) &&
(item.filter != null) &&
(item.filter instanceof BaseAttributeFilter) &&
(item.handback == handback)) {
BaseAttributeFilter oldFilter =
(BaseAttributeFilter) item.filter;
String newNames[] = newFilter.getNames();
String oldNames[] = oldFilter.getNames();
if (newNames.length == 0) {
oldFilter.clear();
} else {
if (oldNames.length != 0) {
for (int i = 0; i < newNames.length; i++)
oldFilter.addAttribute(newNames[i]);
}
}
return;
}
}
}
// General purpose addition of a new entry
entries.add(new BaseNotificationBroadcasterEntry
(listener, filter, handback));
}
}
/**
* Return an <code>MBeanNotificationInfo</code> object describing the
* notifications sent by this MBean.
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[0];
}
/**
* Remove a notification event listener from this MBean.
*
* @param listener The listener to be removed (any and all registrations
* for this listener will be eliminated)
*
* @exception ListenerNotFoundException if this listener is not
* registered in the MBean
*/
@Override
public void removeNotificationListener(NotificationListener listener)
throws ListenerNotFoundException {
synchronized (entries) {
Iterator<BaseNotificationBroadcasterEntry> items =
entries.iterator();
while (items.hasNext()) {
BaseNotificationBroadcasterEntry item = items.next();
if (item.listener == listener)
items.remove();
}
}
}
/**
* Send the specified notification to all interested listeners.
*
* @param notification The notification to be sent
*/
public void sendNotification(Notification notification) {
synchronized (entries) {
for (BaseNotificationBroadcasterEntry item : entries) {
if ((item.filter != null) &&
(!item.filter.isNotificationEnabled(notification)))
continue;
item.listener.handleNotification(notification, item.handback);
}
}
}
}
/**
* Utility class representing a particular registered listener entry.
*/
class BaseNotificationBroadcasterEntry {
public BaseNotificationBroadcasterEntry(NotificationListener listener,
NotificationFilter filter,
Object handback) {
this.listener = listener;
this.filter = filter;
this.handback = handback;
}
public NotificationFilter filter = null;
public Object handback = null;
public NotificationListener listener = null;
}

View File

@@ -0,0 +1,83 @@
/*
* 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.tomcat.util.modeler;
import java.io.Serializable;
import javax.management.MBeanFeatureInfo;
/**
* <p>Convenience base class for <code>AttributeInfo</code> and
* <code>OperationInfo</code> classes that will be used to collect configuration
* information for the <code>ModelMBean</code> beans exposed for management.</p>
*
* @author Craig R. McClanahan
*/
public class FeatureInfo implements Serializable {
static final long serialVersionUID = -911529176124712296L;
protected String description = null;
protected String name = null;
protected MBeanFeatureInfo info = null;
// all have type except Constructor
protected String type = null;
// ------------------------------------------------------------- Properties
/**
* @return the human-readable description of this feature.
*/
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
/**
* @return the name of this feature, which must be unique among features
* in the same collection.
*/
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
/**
* @return the fully qualified Java class name of this element.
*/
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
}

View File

@@ -0,0 +1,17 @@
# 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.
modules.digesterParseError=Error parsing registry data
modules.readDescriptorsError=Error reading descriptors

View File

@@ -0,0 +1,17 @@
# 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.
modules.digesterParseError=Erreur lors de l'analyse des données du registre
modules.readDescriptorsError=Erreur lors de la lecture des descripteurs

View File

@@ -0,0 +1,17 @@
# 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.
modules.digesterParseError=レジストリデータの解析エラー
modules.readDescriptorsError=ディスクリプタ読み取り中のエラー

View File

@@ -0,0 +1,17 @@
# 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.
modules.digesterParseError=레지스트리 데이터를 파싱하는 중 오류 발생
modules.readDescriptorsError=Descriptor들을 읽는 중 오류 발생

View File

@@ -0,0 +1,16 @@
# 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.
modules.readDescriptorsError=读取描述文件出错

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
/*
* 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.tomcat.util.modeler;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.management.MBeanNotificationInfo;
/**
* <p>Internal configuration information for a <code>Notification</code>
* descriptor.</p>
*
* @author Craig R. McClanahan
*/
public class NotificationInfo extends FeatureInfo {
static final long serialVersionUID = -6319885418912650856L;
// ----------------------------------------------------- Instance Variables
/**
* The <code>ModelMBeanNotificationInfo</code> object that corresponds
* to this <code>NotificationInfo</code> instance.
*/
transient MBeanNotificationInfo info = null;
protected String notifTypes[] = new String[0];
protected final ReadWriteLock notifTypesLock = new ReentrantReadWriteLock();
// ------------------------------------------------------------- Properties
/**
* Override the <code>description</code> property setter.
*
* @param description The new description
*/
@Override
public void setDescription(String description) {
super.setDescription(description);
this.info = null;
}
/**
* Override the <code>name</code> property setter.
*
* @param name The new name
*/
@Override
public void setName(String name) {
super.setName(name);
this.info = null;
}
/**
* @return the set of notification types for this MBean.
*/
public String[] getNotifTypes() {
Lock readLock = notifTypesLock.readLock();
readLock.lock();
try {
return this.notifTypes;
} finally {
readLock.unlock();
}
}
// --------------------------------------------------------- Public Methods
/**
* Add a new notification type to the set managed by an MBean.
*
* @param notifType The new notification type
*/
public void addNotifType(String notifType) {
Lock writeLock = notifTypesLock.writeLock();
writeLock.lock();
try {
String results[] = new String[notifTypes.length + 1];
System.arraycopy(notifTypes, 0, results, 0, notifTypes.length);
results[notifTypes.length] = notifType;
notifTypes = results;
this.info = null;
} finally {
writeLock.unlock();
}
}
/**
* Create and return a <code>ModelMBeanNotificationInfo</code> object that
* corresponds to the attribute described by this instance.
* @return the notification info
*/
public MBeanNotificationInfo createNotificationInfo() {
// Return our cached information (if any)
if (info != null)
return info;
// Create and return a new information object
info = new MBeanNotificationInfo
(getNotifTypes(), getName(), getDescription());
//Descriptor descriptor = info.getDescriptor();
//addFields(descriptor);
//info.setDescriptor(descriptor);
return info;
}
/**
* Return a string representation of this notification descriptor.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("NotificationInfo[");
sb.append("name=");
sb.append(name);
sb.append(", description=");
sb.append(description);
sb.append(", notifTypes=");
Lock readLock = notifTypesLock.readLock();
readLock.lock();
try {
sb.append(notifTypes.length);
} finally {
readLock.unlock();
}
sb.append("]");
return sb.toString();
}
}

View File

@@ -0,0 +1,172 @@
/*
* 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.tomcat.util.modeler;
import java.util.Locale;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
/**
* <p>Internal configuration information for an <code>Operation</code>
* descriptor.</p>
*
* @author Craig R. McClanahan
*/
public class OperationInfo extends FeatureInfo {
static final long serialVersionUID = 4418342922072614875L;
// ----------------------------------------------------------- Constructors
/**
* Standard zero-arguments constructor.
*/
public OperationInfo() {
super();
}
// ----------------------------------------------------- Instance Variables
protected String impact = "UNKNOWN";
protected String role = "operation";
protected final ReadWriteLock parametersLock = new ReentrantReadWriteLock();
protected ParameterInfo parameters[] = new ParameterInfo[0];
// ------------------------------------------------------------- Properties
/**
* @return the "impact" of this operation, which should be
* a (case-insensitive) string value "ACTION", "ACTION_INFO",
* "INFO", or "UNKNOWN".
*/
public String getImpact() {
return this.impact;
}
public void setImpact(String impact) {
if (impact == null)
this.impact = null;
else
this.impact = impact.toUpperCase(Locale.ENGLISH);
}
/**
* @return the role of this operation ("getter", "setter", "operation", or
* "constructor").
*/
public String getRole() {
return this.role;
}
public void setRole(String role) {
this.role = role;
}
/**
* @return the fully qualified Java class name of the return type for this
* operation.
*/
public String getReturnType() {
if(type == null) {
type = "void";
}
return type;
}
public void setReturnType(String returnType) {
this.type = returnType;
}
/**
* @return the set of parameters for this operation.
*/
public ParameterInfo[] getSignature() {
Lock readLock = parametersLock.readLock();
readLock.lock();
try {
return this.parameters;
} finally {
readLock.unlock();
}
}
// --------------------------------------------------------- Public Methods
/**
* Add a new parameter to the set of arguments for this operation.
*
* @param parameter The new parameter descriptor
*/
public void addParameter(ParameterInfo parameter) {
Lock writeLock = parametersLock.writeLock();
writeLock.lock();
try {
ParameterInfo results[] = new ParameterInfo[parameters.length + 1];
System.arraycopy(parameters, 0, results, 0, parameters.length);
results[parameters.length] = parameter;
parameters = results;
this.info = null;
} finally {
writeLock.unlock();
}
}
/**
* Create and return a <code>ModelMBeanOperationInfo</code> object that
* corresponds to the attribute described by this instance.
* @return the operation info
*/
MBeanOperationInfo createOperationInfo() {
// Return our cached information (if any)
if (info == null) {
// Create and return a new information object
int impact = MBeanOperationInfo.UNKNOWN;
if ("ACTION".equals(getImpact()))
impact = MBeanOperationInfo.ACTION;
else if ("ACTION_INFO".equals(getImpact()))
impact = MBeanOperationInfo.ACTION_INFO;
else if ("INFO".equals(getImpact()))
impact = MBeanOperationInfo.INFO;
info = new MBeanOperationInfo(getName(), getDescription(),
getMBeanParameterInfo(),
getReturnType(), impact);
}
return (MBeanOperationInfo)info;
}
protected MBeanParameterInfo[] getMBeanParameterInfo() {
ParameterInfo params[] = getSignature();
MBeanParameterInfo parameters[] =
new MBeanParameterInfo[params.length];
for (int i = 0; i < params.length; i++)
parameters[i] = params[i].createParameterInfo();
return parameters;
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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.tomcat.util.modeler;
import javax.management.MBeanParameterInfo;
/**
* <p>Internal configuration information for a <code>Parameter</code>
* descriptor.</p>
*
* @author Craig R. McClanahan
*/
public class ParameterInfo extends FeatureInfo {
static final long serialVersionUID = 2222796006787664020L;
// ----------------------------------------------------------- Constructors
/**
* Standard zero-arguments constructor.
*/
public ParameterInfo() {
super();
}
/**
* Create and return a <code>MBeanParameterInfo</code> object that
* corresponds to the parameter described by this instance.
* @return a parameter info
*/
public MBeanParameterInfo createParameterInfo() {
// Return our cached information (if any)
if (info == null) {
info = new MBeanParameterInfo
(getName(), getType(), getDescription());
}
return (MBeanParameterInfo)info;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
/*
* 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.tomcat.util.modeler;
import java.util.List;
import javax.management.ObjectName;
/**
* Interface for modeler MBeans.
*
* This is the main entry point into modeler. It provides methods to create
* and manipulate model mbeans and simplify their use.
*
* Starting with version 1.1, this is no longer a singleton and the static
* methods are strongly deprecated. In a container environment we can expect
* different applications to use different registries.
*
* @author Craig R. McClanahan
* @author Costin Manolache
*
* @since 1.1
*/
public interface RegistryMBean {
/**
* Invoke an operation on a set of mbeans.
*
* @param mbeans List of ObjectNames
* @param operation Operation to perform. Typically "init" "start" "stop" or "destroy"
* @param failFirst Behavior in case of exceptions - if false we'll ignore
* errors
* @throws Exception Error invoking operation
*/
public void invoke(List<ObjectName> mbeans, String operation, boolean failFirst)
throws Exception;
/**
* Register a bean by creating a modeler mbean and adding it to the
* MBeanServer.
*
* If metadata is not loaded, we'll look up and read a file named
* "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package
* or parent.
*
* If the bean is an instance of DynamicMBean. it's metadata will be converted
* to a model mbean and we'll wrap it - so modeler services will be supported
*
* If the metadata is still not found, introspection will be used to extract
* it automatically.
*
* If an mbean is already registered under this name, it'll be first
* unregistered.
*
* If the component implements MBeanRegistration, the methods will be called.
* If the method has a method "setRegistry" that takes a RegistryMBean as
* parameter, it'll be called with the current registry.
*
*
* @param bean Object to be registered
* @param oname Name used for registration
* @param type The type of the mbean, as declared in mbeans-descriptors. If
* null, the name of the class will be used. This can be used as a hint or
* by subclasses.
* @throws Exception Error registering MBean
*
* @since 1.1
*/
public void registerComponent(Object bean, String oname, String type)
throws Exception;
/**
* Unregister a component. We'll first check if it is registered,
* and mask all errors. This is mostly a helper.
*
* @param oname The name used by the bean
*
* @since 1.1
*/
public void unregisterComponent(String oname);
/**
* Return an int ID for faster access. Will be used for notifications
* and for other operations we want to optimize.
*
* @param domain Namespace
* @param name Type of the notification
* @return A unique id for the domain:name combination
* @since 1.1
*/
public int getId(String domain, String name);
/**
* Reset all metadata cached by this registry. Should be called
* to support reloading. Existing mbeans will not be affected or modified.
*
* It will be called automatically if the Registry is unregistered.
* @since 1.1
*/
public void stop();
}

View File

@@ -0,0 +1,34 @@
/*
* 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.tomcat.util.modeler;
public class Util {
private Util() {
// Utility class. Hide default constructor.
}
public static boolean objectNameValueNeedsQuote(String input) {
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (ch == ',' || ch == '=' || ch == ':' || ch == '*' || ch == '?') {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<!--
DTD for the Model MBeans Configuration File
To support validation of your configuration file, include the following
DOCTYPE element at the beginning (after the "xml" declaration):
<!DOCTYPE mbeans-descriptors PUBLIC
"-//Apache Software Foundation//DTD Model MBeans Configuration File"
"http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">
-->
<!-- ========== Defined Types ============================================= -->
<!-- A "Boolean" is the string representation of a boolean (true or false)
variable.
-->
<!ENTITY % Boolean "(true|false|yes|no)">
<!-- A "ClassName" is the fully qualified name of a Java class that is
instantiated to provide the functionality of the enclosing element.
-->
<!ENTITY % ClassName "CDATA">
<!-- A "MethodName" is the name of a constructor or method, which must
be legal according to the syntax requirements of the Java language.
-->
<!ENTITY % MethodName "CDATA">
<!-- A "VariableName" is the name of a variable or parameter, which must
be legal according to the syntax requirements of the Java language.
-->
<!ENTITY % VariableName "CDATA">
<!-- ========== Element Definitions ======================================= -->
<!-- The "mbeans-descriptors" element is the root of the configuration file
hierarchy, and contains nested elements for all of the other
configuration settings. Remaining element definitions are listed
in alphabetical order.
-->
<!ELEMENT mbeans-descriptors (mbean*)>
<!ATTLIST mbeans-descriptors id ID #IMPLIED>
<!-- The "attribute" element describes a JavaBeans property of an MBean.
The following attributes are supported:
description Human-readable description of this attribute.
displayName Display name of this attribute.
getMethod Name of the property getter method, if it does
not follow standard JavaBeans naming patterns.
is Boolean value indicating whether or not this
attribute is a boolean with an "is" getter method.
By default, this is set to "false".
name Name of this JavaBeans property, conforming to
standard naming design patterns.
readable Boolean value indicating whether or not this
attribute is readable by management applications.
By default, this is set to "true".
setMethod Name of the property setter method, if it does
not follow standard JavaBeans naming patterns.
type Fully qualified Java class name of this attribute.
writeable Boolean value indicating whether or not this
attribute is writeable by management applications.
By default, this is set to "true".
-->
<!ELEMENT attribute (descriptor?)>
<!ATTLIST attribute id ID #IMPLIED>
<!ATTLIST attribute description CDATA #IMPLIED>
<!ATTLIST attribute displayName CDATA #IMPLIED>
<!ATTLIST attribute getMethod %MethodName; #IMPLIED>
<!ATTLIST attribute is %Boolean; #IMPLIED>
<!ATTLIST attribute name %VariableName; #IMPLIED>
<!ATTLIST attribute readable %Boolean; #IMPLIED>
<!ATTLIST attribute setMethod %MethodName; #IMPLIED>
<!ATTLIST attribute type %ClassName; #IMPLIED>
<!ATTLIST attribute writeable %Boolean; #IMPLIED>
<!-- The "constructor" element describes a public constructor for the
underlying actual class. It may contain nested "parameter" elements
for the various arguments to this constructor. The following attributes
are supported:
displayName Display name of this constructor.
name Name of this constructor (by Java convention, this must
be the same as the base class name).
-->
<!ELEMENT constructor (descriptor?, parameter*)>
<!ATTLIST constructor id ID #IMPLIED>
<!ATTLIST constructor displayName CDATA #IMPLIED>
<!ATTLIST constructor name %VariableName; #IMPLIED>
<!-- The "descriptor" element groups a set of descriptor fields whose
values will be included in the Descriptor for the corresponding
metadata info classes.
-->
<!ELEMENT descriptor (field*)>
<!ATTLIST descriptor id ID #IMPLIED>
<!-- The "field" element represents a single name/value pair that will
be included in the Descriptor corresponding to our enclosing
"descriptor" element. The following attributes are supported:
name Field name of the field to be included
value Field value of the field to be included
(will be stored as a String)
-->
<!ELEMENT field EMPTY>
<!ATTLIST field id ID #IMPLIED>
<!ATTLIST field name CDATA #REQUIRED>
<!ATTLIST field value CDATA #REQUIRED>
<!-- The "mbean" element describes a particular JMX ModelMBean implementation,
including the information necessary to construct the corresponding
ModelMBeanInfo structures. The following attributes are supported:
className Fully qualified Java class name of the ModelMBean
implementation class. If not specified, the standard
implementation provided by JMX will be utilized.
description Human-readable description of this managed bean.
domain The JMX MBeanServer domain in which the ModelMBean
created by this managed bean should be registered,
when creating its ObjectName.
group Optional name of a "grouping classification" that can
be used to select groups of similar MBean implementation
classes.
name Unique name of this MBean (normally corresponds to the
base class name of the corresponding server component).
type Fully qualified Java class name of the underlying
managed resource implementation class.
-->
<!ELEMENT mbean (descriptor?, attribute*, constructor*, notification*, operation*)>
<!ATTLIST mbean id ID #IMPLIED>
<!ATTLIST mbean className %ClassName; #IMPLIED>
<!ATTLIST mbean description CDATA #IMPLIED>
<!ATTLIST mbean domain CDATA #IMPLIED>
<!ATTLIST mbean group CDATA #IMPLIED>
<!ATTLIST mbean name %MethodName; #IMPLIED>
<!ATTLIST mbean type %ClassName; #IMPLIED>
<!-- The "notification" element describes the notification types that are
generated by a particular managed bean. The following attributes
are supported:
description Human-readable description of these notification events.
name Name of this set of notification event types.
-->
<!ELEMENT notification (descriptor?, notification-type*)>
<!ATTLIST notification id ID #IMPLIED>
<!ATTLIST notification description CDATA #IMPLIED>
<!ATTLIST notification name %VariableName; #IMPLIED>
<!-- The nested content of the "notification-type" element is the event string
of an event that can be emitted by this MBean.
-->
<!ELEMENT notification-type (#PCDATA)>
<!ATTLIST notification-type id ID #IMPLIED>
<!-- The "operation" element describes a the signature of a public method
that is accessible to management applications. The following attributes
are supported:
description Human-readable description of this operation.
impact Indication of the impact of this method:
ACTION (write like), ACTION-INFO (write+read like)
INFO (read like), or UNKNOWN.
name Name of this public method.
returnType Fully qualified Java class name of the return
type of this method.
-->
<!ELEMENT operation (descriptor?, parameter*)>
<!ATTLIST operation id ID #IMPLIED>
<!ATTLIST operation description CDATA #IMPLIED>
<!ATTLIST operation impact CDATA #IMPLIED>
<!ATTLIST operation name %VariableName; #IMPLIED>
<!ATTLIST operation returnType %ClassName; #IMPLIED>
<!-- The "parameter" element describes a single argument that will be passed
to a constructor or operation. The following attributes are supported:
description Human-readable description of this parameter.
name Java language name of this parameter.
type Fully qualified Java class name of this parameter.
-->
<!ELEMENT parameter EMPTY>
<!ATTLIST parameter id ID #IMPLIED>
<!ATTLIST parameter description CDATA #IMPLIED>
<!ATTLIST parameter name %VariableName; #IMPLIED>
<!ATTLIST parameter type %ClassName; #IMPLIED>

View File

@@ -0,0 +1,182 @@
/*
* 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.tomcat.util.modeler.modules;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.management.ObjectName;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tomcat.util.modeler.ManagedBean;
import org.apache.tomcat.util.modeler.Registry;
public class MbeansDescriptorsDigesterSource extends ModelerSource
{
private static final Log log =
LogFactory.getLog(MbeansDescriptorsDigesterSource.class);
private static final Object dLock = new Object();
private Registry registry;
private final List<ObjectName> mbeans = new ArrayList<>();
private static Digester digester = null;
private static Digester createDigester() {
Digester digester = new Digester();
digester.setNamespaceAware(false);
digester.setValidating(false);
URL url = Registry.getRegistry(null, null).getClass().getResource
("/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd");
digester.register
("-//Apache Software Foundation//DTD Model MBeans Configuration File",
url.toString());
// Configure the parsing rules
digester.addObjectCreate
("mbeans-descriptors/mbean",
"org.apache.tomcat.util.modeler.ManagedBean");
digester.addSetProperties
("mbeans-descriptors/mbean");
digester.addSetNext
("mbeans-descriptors/mbean",
"add",
"java.lang.Object");
digester.addObjectCreate
("mbeans-descriptors/mbean/attribute",
"org.apache.tomcat.util.modeler.AttributeInfo");
digester.addSetProperties
("mbeans-descriptors/mbean/attribute");
digester.addSetNext
("mbeans-descriptors/mbean/attribute",
"addAttribute",
"org.apache.tomcat.util.modeler.AttributeInfo");
digester.addObjectCreate
("mbeans-descriptors/mbean/notification",
"org.apache.tomcat.util.modeler.NotificationInfo");
digester.addSetProperties
("mbeans-descriptors/mbean/notification");
digester.addSetNext
("mbeans-descriptors/mbean/notification",
"addNotification",
"org.apache.tomcat.util.modeler.NotificationInfo");
digester.addObjectCreate
("mbeans-descriptors/mbean/notification/descriptor/field",
"org.apache.tomcat.util.modeler.FieldInfo");
digester.addSetProperties
("mbeans-descriptors/mbean/notification/descriptor/field");
digester.addSetNext
("mbeans-descriptors/mbean/notification/descriptor/field",
"addField",
"org.apache.tomcat.util.modeler.FieldInfo");
digester.addCallMethod
("mbeans-descriptors/mbean/notification/notification-type",
"addNotifType", 0);
digester.addObjectCreate
("mbeans-descriptors/mbean/operation",
"org.apache.tomcat.util.modeler.OperationInfo");
digester.addSetProperties
("mbeans-descriptors/mbean/operation");
digester.addSetNext
("mbeans-descriptors/mbean/operation",
"addOperation",
"org.apache.tomcat.util.modeler.OperationInfo");
digester.addObjectCreate
("mbeans-descriptors/mbean/operation/descriptor/field",
"org.apache.tomcat.util.modeler.FieldInfo");
digester.addSetProperties
("mbeans-descriptors/mbean/operation/descriptor/field");
digester.addSetNext
("mbeans-descriptors/mbean/operation/descriptor/field",
"addField",
"org.apache.tomcat.util.modeler.FieldInfo");
digester.addObjectCreate
("mbeans-descriptors/mbean/operation/parameter",
"org.apache.tomcat.util.modeler.ParameterInfo");
digester.addSetProperties
("mbeans-descriptors/mbean/operation/parameter");
digester.addSetNext
("mbeans-descriptors/mbean/operation/parameter",
"addParameter",
"org.apache.tomcat.util.modeler.ParameterInfo");
return digester;
}
public void setRegistry(Registry reg) {
this.registry=reg;
}
public void setSource( Object source ) {
this.source=source;
}
@Override
public List<ObjectName> loadDescriptors( Registry registry, String type,
Object source) throws Exception {
setRegistry(registry);
setSource(source);
execute();
return mbeans;
}
public void execute() throws Exception {
if (registry == null) {
registry = Registry.getRegistry(null, null);
}
InputStream stream = (InputStream) source;
List<ManagedBean> loadedMbeans = new ArrayList<>();
synchronized(dLock) {
if (digester == null) {
digester = createDigester();
}
// Process the input file to configure our registry
try {
// Push our registry object onto the stack
digester.push(loadedMbeans);
digester.parse(stream);
} catch (Exception e) {
log.error(sm.getString("modules.digesterParseError"), e);
throw e;
} finally {
digester.reset();
}
}
for (ManagedBean loadedMbean : loadedMbeans) {
registry.addManagedBean(loadedMbean);
}
}
}

View File

@@ -0,0 +1,392 @@
/*
* 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.tomcat.util.modeler.modules;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Map.Entry;
import javax.management.ObjectName;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.modeler.AttributeInfo;
import org.apache.tomcat.util.modeler.ManagedBean;
import org.apache.tomcat.util.modeler.OperationInfo;
import org.apache.tomcat.util.modeler.ParameterInfo;
import org.apache.tomcat.util.modeler.Registry;
public class MbeansDescriptorsIntrospectionSource extends ModelerSource
{
private static final Log log = LogFactory.getLog(MbeansDescriptorsIntrospectionSource.class);
private Registry registry;
private String type;
private final List<ObjectName> mbeans = new ArrayList<>();
public void setRegistry(Registry reg) {
this.registry=reg;
}
/**
* Used if a single component is loaded
*
* @param type The type
*/
public void setType( String type ) {
this.type=type;
}
public void setSource( Object source ) {
this.source=source;
}
@Override
public List<ObjectName> loadDescriptors(Registry registry, String type,
Object source) throws Exception {
setRegistry(registry);
setType(type);
setSource(source);
execute();
return mbeans;
}
public void execute() throws Exception {
if( registry==null ) registry=Registry.getRegistry(null, null);
try {
ManagedBean managed = createManagedBean(registry, null,
(Class<?>)source, type);
if( managed==null ) return;
managed.setName( type );
registry.addManagedBean(managed);
} catch( Exception ex ) {
log.error(sm.getString("modules.readDescriptorsError"), ex);
}
}
// ------------ Implementation for non-declared introspection classes
private static final Hashtable<String,String> specialMethods = new Hashtable<>();
static {
specialMethods.put( "preDeregister", "");
specialMethods.put( "postDeregister", "");
}
private static final Class<?>[] supportedTypes = new Class[] {
Boolean.class,
Boolean.TYPE,
Byte.class,
Byte.TYPE,
Character.class,
Character.TYPE,
Short.class,
Short.TYPE,
Integer.class,
Integer.TYPE,
Long.class,
Long.TYPE,
Float.class,
Float.TYPE,
Double.class,
Double.TYPE,
String.class,
String[].class,
BigDecimal.class,
BigInteger.class,
ObjectName.class,
Object[].class,
java.io.File.class,
};
/**
* Check if this class is one of the supported types.
* If the class is supported, returns true. Otherwise,
* returns false.
* @param ret The class to check
* @return boolean True if class is supported
*/
private boolean supportedType(Class<?> ret) {
for (int i = 0; i < supportedTypes.length; i++) {
if (ret == supportedTypes[i]) {
return true;
}
}
if (isBeanCompatible(ret)) {
return true;
}
return false;
}
/**
* Check if this class conforms to JavaBeans specifications.
* If the class is conformant, returns true.
*
* @param javaType The class to check
* @return boolean True if the class is compatible.
*/
private boolean isBeanCompatible(Class<?> javaType) {
// Must be a non-primitive and non array
if (javaType.isArray() || javaType.isPrimitive()) {
return false;
}
// Anything in the java or javax package that
// does not have a defined mapping is excluded.
if (javaType.getName().startsWith("java.") ||
javaType.getName().startsWith("javax.")) {
return false;
}
try {
javaType.getConstructor(new Class[]{});
} catch (java.lang.NoSuchMethodException e) {
return false;
}
// Make sure superclass is compatible
Class<?> superClass = javaType.getSuperclass();
if (superClass != null &&
superClass != java.lang.Object.class &&
superClass != java.lang.Exception.class &&
superClass != java.lang.Throwable.class) {
if (!isBeanCompatible(superClass)) {
return false;
}
}
return true;
}
/**
* Process the methods and extract 'attributes', methods, etc.
*
* @param realClass The class to process
* @param methods The methods to process
* @param attMap The attribute map (complete)
* @param getAttMap The readable attributes map
* @param setAttMap The settable attributes map
* @param invokeAttMap The invokable attributes map
*/
private void initMethods(Class<?> realClass, Method methods[], Hashtable<String,Method> attMap,
Hashtable<String,Method> getAttMap, Hashtable<String,Method> setAttMap,
Hashtable<String,Method> invokeAttMap) {
for (int j = 0; j < methods.length; ++j) {
String name = methods[j].getName();
if (Modifier.isStatic(methods[j].getModifiers())) {
continue;
}
if (!Modifier.isPublic(methods[j].getModifiers())) {
if (log.isDebugEnabled()) {
log.debug("Not public " + methods[j] );
}
continue;
}
if (methods[j].getDeclaringClass() == Object.class) {
continue;
}
Class<?> params[] = methods[j].getParameterTypes();
if (name.startsWith("get") && params.length==0) {
Class<?> ret = methods[j].getReturnType();
if (!supportedType(ret)) {
if (log.isDebugEnabled()) {
log.debug("Unsupported type " + methods[j]);
}
continue;
}
name=unCapitalize(name.substring(3));
getAttMap.put(name, methods[j]);
// just a marker, we don't use the value
attMap.put(name, methods[j]);
} else if(name.startsWith("is") && params.length == 0) {
Class<?> ret = methods[j].getReturnType();
if (Boolean.TYPE != ret) {
if (log.isDebugEnabled()) {
log.debug("Unsupported type " + methods[j] + " " + ret );
}
continue;
}
name = unCapitalize(name.substring(2));
getAttMap.put(name, methods[j]);
// just a marker, we don't use the value
attMap.put(name, methods[j]);
} else if (name.startsWith("set") && params.length == 1) {
if (!supportedType(params[0])) {
if (log.isDebugEnabled()) {
log.debug("Unsupported type " + methods[j] + " " + params[0]);
}
continue;
}
name = unCapitalize(name.substring(3));
setAttMap.put(name, methods[j]);
attMap.put(name, methods[j]);
} else {
if (params.length == 0) {
if (specialMethods.get(methods[j].getName()) != null) {
continue;
}
invokeAttMap.put(name, methods[j]);
} else {
boolean supported = true;
for (int i = 0; i < params.length; i++ ) {
if (!supportedType(params[i])) {
supported = false;
break;
}
}
if (supported) {
invokeAttMap.put( name, methods[j]);
}
}
}
}
}
/**
* XXX Find if the 'className' is the name of the MBean or
* the real class ( I suppose first )
* XXX Read (optional) descriptions from a .properties, generated
* from source
* XXX Deal with constructors
*
* @param registry The Bean registry (not used)
* @param domain The bean domain (not used)
* @param realClass The class to analyze
* @param type The bean type
* @return ManagedBean The create MBean
*/
public ManagedBean createManagedBean(Registry registry, String domain,
Class<?> realClass, String type)
{
ManagedBean mbean= new ManagedBean();
Method methods[]=null;
Hashtable<String,Method> attMap = new Hashtable<>();
// key: attribute val: getter method
Hashtable<String,Method> getAttMap = new Hashtable<>();
// key: attribute val: setter method
Hashtable<String,Method> setAttMap = new Hashtable<>();
// key: operation val: invoke method
Hashtable<String,Method> invokeAttMap = new Hashtable<>();
methods = realClass.getMethods();
initMethods(realClass, methods, attMap, getAttMap, setAttMap, invokeAttMap );
try {
Enumeration<String> en = attMap.keys();
while( en.hasMoreElements() ) {
String name = en.nextElement();
AttributeInfo ai=new AttributeInfo();
ai.setName( name );
Method gm = getAttMap.get(name);
if( gm!=null ) {
//ai.setGetMethodObj( gm );
ai.setGetMethod( gm.getName());
Class<?> t=gm.getReturnType();
if( t!=null )
ai.setType( t.getName() );
}
Method sm = setAttMap.get(name);
if( sm!=null ) {
//ai.setSetMethodObj(sm);
Class<?> t = sm.getParameterTypes()[0];
if( t!=null )
ai.setType( t.getName());
ai.setSetMethod( sm.getName());
}
ai.setDescription("Introspected attribute " + name);
if( log.isDebugEnabled()) log.debug("Introspected attribute " +
name + " " + gm + " " + sm);
if( gm==null )
ai.setReadable(false);
if( sm==null )
ai.setWriteable(false);
if( sm!=null || gm!=null )
mbean.addAttribute(ai);
}
// This map is populated by iterating the methods (which end up as
// values in the Map) and obtaining the key from the value. It is
// impossible for a key to be associated with a null value.
for (Entry<String,Method> entry : invokeAttMap.entrySet()) {
String name = entry.getKey();
Method m = entry.getValue();
OperationInfo op=new OperationInfo();
op.setName(name);
op.setReturnType(m.getReturnType().getName());
op.setDescription("Introspected operation " + name);
Class<?> parms[] = m.getParameterTypes();
for(int i=0; i<parms.length; i++ ) {
ParameterInfo pi=new ParameterInfo();
pi.setType(parms[i].getName());
pi.setName(("param" + i).intern());
pi.setDescription(("Introspected parameter param" + i).intern());
op.addParameter(pi);
}
mbean.addOperation(op);
}
if( log.isDebugEnabled())
log.debug("Setting name: " + type );
mbean.setName( type );
return mbean;
} catch( Exception ex ) {
ex.printStackTrace();
return null;
}
}
// -------------------- Utils --------------------
/**
* Converts the first character of the given
* String into lower-case.
*
* @param name The string to convert
* @return String
*/
private static String unCapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
}

View File

@@ -0,0 +1,44 @@
/*
* 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.tomcat.util.modeler.modules;
import java.util.List;
import javax.management.ObjectName;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.res.StringManager;
/**
* Source for descriptor data. More sources can be added.
*/
public abstract class ModelerSource {
protected static final StringManager sm = StringManager.getManager(Registry.class);
protected Object source;
/**
* Load data, returns a list of items.
*
* @param registry The registry
* @param type The bean registry type
* @param source Introspected object or some other source
* @return a list of object names
* @throws Exception Error loading descriptors
*/
public abstract List<ObjectName> loadDescriptors(Registry registry,
String type, Object source) throws Exception;
}

View File

@@ -0,0 +1,59 @@
<!--
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.
-->
<html>
<head>
<title>org.apache.commons.modeler.modules</title>
</head>
<body>
<p>Implementation classes - should not be used directly. The API is not stable
but eventually the code will be refactored as a collection of mbeans that will be useable
( more or less ) independently.</p>
<p>The MbeanDescriptors* classes are used to extract metadata from different sources. They
are result of few stages of refactoring - now they look very similar with ant tasks and are
close to normal mbeans, with an execute() method. DOM, SER, Introspection and Dynamic mbean
will load metadata from the corresponding sources.
</p>
<p>MbeansSource will load an extended MLET file, similar with jboss. It is not completely
implemented - only modeler mbeans and dynamic mbeans are loaded. The important characteristic
is that all declared mbeans will be registered in the mbean server as model mbeans. For
regular java classes, the description will be used to construct the model mbean. DynamicMbeans
metadata will be converted to model mbean and the model mbean wrapper will be loaded.</p>
<p>The goal of MbeansSource is to implement a simple persistence mechanism. Since all components
are model mbeans, we can detect all changes. The source will be loaded as DOM and modifications
will be made to the tree. The save() method will save the DOM tree - preserving all comments
and having only the changes that are needed.</p>
<p>There are few remaining issues. First, we need to use the persistence metadata to avoid
saving transient fields ( we save an attribute when we detect a change - but we don't know
if this attribute should be saved ). The solution is to use the persistence fields in the
spec - with some reasonable defaults or patterns for introspection or backward compat.
</p>
<p>Another problem is implementing adding and removing components. In catalina, a
factory is used to create the components, and save will operate on all mbeans.
For creation we need to also use a factory - using the "Type" as a parameter. This
will also work very well with Ant1.6 where we can use the component factory to
do a "natural" mapping ( i.e. mbeans can be treated as tasks, with attributes as
task attributes ). The second part can be solve by either using a parameter on
the factory method ( saveTo ? ), or by having a single mbeans source per domain.
</p>
</body>
</html>

View File

@@ -0,0 +1,248 @@
<!--
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.
-->
<html>
<head>
<title>Package Documentation for COMMONS-MODELER</title>
</head>
<body bgcolor="white">
<p>The <em>Modeler</em> component of the Commons project
offers convenient support for configuring and instantiating Model MBeans
(management beans), as described in the JMX Specification. It is typically
used within a server-based application that wants to expose management
features via JMX. See the
<a href="http://java.sun.com/products/JavaManagement/download.html">
JMX Specification (Version 1.1)</a> for more information about Model MBeans
and other JMX concepts.</p>
<p>Model MBeans are very powerful - and the JMX specification includes a
mechanism to use a standard JMX-provided base class to satisfy many of the
requirements, without having to create custom Model MBean implementation
classes yourself. However, one of the requirements in creating such a
Model MBean is to create the corresponding metadata information (i.e. an
implementation of the
<code>javax.management.modelmbean.ModelMBeanInfo</code> interface and its
corresponding subordinate interfaces). Creating this information can be
tedious and error prone. The <em>Modeler</em> package makes the process
much simpler, because the required information is constructed dynamically
from an easy-to-understand XML description of the metadata. Once you have
the metadata defined, and registered at runtime in the provided
<a href="Registry.html">Registry</a>, <em>Modeler</em> also supports
convenient factory methods to instantiate new Model MBean instances for you.
</p>
<p>The steps required to use Modeler in your server-based application are
described in detail below. You can find some simple usage code in the unit
tests that come with Modeler (in the <code>src/test</code> subdirectory of the
source distribution), and much more complex usage code in Tomcat 4.1 (in the
<code>org.apache.catalina.mbeans</code> package).</p>. More advanced uses can
be found in Tomcat 5.
<h2>1. Acquire a JMX Implementation</h2>
<p><em>Modeler</em> has been tested with different JMX implementations:
<ul>
<li>JMX Reference Implementation (version 1.0.1 or later) -
<a href="http://java.sun.com/products/JavaManagement/download.html">
http://java.sun.com/products/JavaManagement/download.html</a></li>
<li>MX4J (version 1.1 or later) -
<a href="http://mx4j.sourceforge.net/">http://mx4j.sourceforge.net</a></li>
<li>JBoss MX
<a href="http://www.jboss.org/">http://www.jboss.org</a></li>
</ul>
<p>After unpacking the release, you will need to ensure that the appropriate
JAR file (<code>jmxri.jar</code> or <code>mx4j.jar</code>) is included on your
compilation classpath, and in the classpath of your server application when it
is executed.</p>
<h2>2. Create a Modeler Configuration File</h2>
<p><em>Modeler</em> requires that you construct a configuration file that
describes the metadata ultimately need to construct the
<code>javax.management.modelmbean.ModelMBeanInfo</code> structure that is
required by JMX. Your XML file must conform to the
<a href="../../../../../../mbeans-descriptors.dtd">mbeans-descriptors.dtd</a>
DTD that defines the acceptable structure.</p>
<p>Fundamentally, you will be constructing an <code>&lt;mbean&gt;</code>
element for each type of Model MBean that a registry will know how to create.
Nested within this element will be other elements describing the constructors,
attributes, operations, and notifications associated with this MBean. See
the comments in the DTD for detailed information about the valid attributes
and their meanings.</p>
<p>A simple example configuration file might include the following components
(abstracted from the real definitions found in Tomcat 4.1's use of Modeler):
</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE mbeans-descriptors PUBLIC
"-//Apache Software Foundation//DTD Model MBeans Configuration File"
"http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd"&gt;
&lt;mbeans-descriptors&gt;
&lt;!-- ... other MBean definitions ... --&gt;
&lt;mbean name="Group"
className="org.apache.catalina.mbeans.GroupMBean"
description="Group from a user database"
domain="Users"
group="Group"
type="org.apache.catalina.Group"&gt;
&lt;attribute name="description"
description="Description of this group"
type="java.lang.String"/&gt;
&lt;attribute name="groupname"
description="Group name of this group"
type="java.lang.String"/&gt;
&lt;attribute name="roles"
description="MBean Names of roles for this group"
type="java.lang.String[]"
writeable="false"/&gt;
&lt;attribute name="users"
description="MBean Names of user members of this group"
type="java.lang.String[]"
writeable="false"/&gt;
&lt;operation name="addRole"
description="Add a new authorized role for this group"
impact="ACTION"
returnType="void"&gt;
&lt;parameter name="role"
description="Role to be added"
type="java.lang.String"/&gt;
&lt;/operation&gt;
&lt;operation name="removeRole"
description="Remove an old authorized role for this group"
impact="ACTION"
returnType="void"&gt;
&lt;parameter name="role"
description="Role to be removed"
type="java.lang.String"/&gt;
&lt;/operation&gt;
&lt;operation name="removeRoles"
description="Remove all authorized roles for this group"
impact="ACTION"
returnType="void"&gt;
&lt;/operation&gt;
&lt;/mbean&gt;
&lt;!-- ... other MBean definitions ... --&gt;
&lt;/mbeans-descriptors&gt;
</pre>
<p>This MBean represents an instance of <em>org.apache.catalina.Group</em>,
which is an entity representing a group of users (with a shared set of security
roles that all users in the group inherit) in a user database. This MBean
advertises support for four attributes (description, groupname, roles, and
users) that roughly correspond to JavaBean properties. By default, attributes
are assumed to have read/write access. For this particular MBean, the roles
and users attributes are read-only (<code>writeable="false"</code>). Finally,
this MBean supports three operations (addRole, removeRole, and
removeRoles) that roughly correspond to JavaBean methods on the underlying
component.</p>
<p>In general, <em>Modeler</em> provides a standard ModelMBean implementation
that simply passes on JMX calls on attributes and operations directly through
to the managed component that the ModelMBean is associated with. For special
case requirements, you can define a subclass of
<a href="BaseModelMBean.html">BaseModelMBean</a> that provides override
methods for one or more of these attributes (i.e. the property getter and/or
setter methods) and operations (i.e. direct method calls).
<p>For this particular MBean, a custom BaseModelMBean implementation subclass
is described (<code>org.apache.catalina.mbeans.GroupMBean</code>) is
configured. It was necessary in this particular case because several of the
underlying Catalina component's methods deal with internal objects or arrays of
objects, rather than just the Strings and primitives that are supported by all
JMX clients. Thus, the following method on the <code>Group</code> interface:
</p>
<pre>
public void addRole(Role role);
</pre>
<p>is represented, in the MBean, by an <code>addRole</code> method that takes
a String argument representing the role name of the required role. The MBean's
implementation class acts as an adapter, and looks up the required Role
object (by name) before calling the <code>addRole</code> method on the
underlying <code>Group</code> instance within the Server.</p>
<h2>3. Create Modeler Registry at Startup Time</h2>
<p>The metadata information, and the corresponding Model MBean factory, is
represented at runtime in an instance of <a href="Registry.html">Registry</a>
whose contents are initialized from the configuration file prepared as was
described above. Typically, such a file will be included in the JAR file
containing the MBean implementation classes themselves, and loaded as follows:
</p>
<pre>
URL url= this.getClass().getResource
("/com/mycompany/mypackage/mbeans-descriptors.xml");
Registry registry = Registry.getRegistry();
registry.loadMetadata(url);
</pre>
<p>Besides using the configuration file, it is possible to configure the
registry metadata by hand, using the <code>addManagedBean()</code> and
<code>removeManagedBean()</code> methods. However, most users will find
the standard support for loading a configuration file to be convenient
and sufficient.</p>
<p>Modeler will also look for an mbeans-descriptors.xml in the same package
with the class being registered and in its parent. If no metadata is found,
modeler will use a number of simple patterns, similar with the ones used by
ant, to determine a reasonable metadata</p>
<p>In a future version we should also support xdoclet-based generation of the
descriptors</p>
<h2>4. Instantiate Model MBeans As Needed</h2>
<p>When your server application needs to instantiate a new MBean and register
it with the corresponding <code>MBeanServer</code>, it can execute code like
this:</p>
<pre>
Group group = ... managed component instance ...;
MBeanServer mserver = registry.getMBeanServer();
String oname="myDomain:type=Group,name=myGroup";
registry.registerComponent( group, oname, "Group" );
</pre>
<p>After the Model MBean has been created and registered, it is accessible to
JMX clients through the standard JMX client APIs.
</p>
</body>
</html>