init
This commit is contained in:
164
java/org/apache/tomcat/util/modeler/AttributeInfo.java
Normal file
164
java/org/apache/tomcat/util/modeler/AttributeInfo.java
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
160
java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java
Normal file
160
java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
915
java/org/apache/tomcat/util/modeler/BaseModelMBean.java
Normal file
915
java/org/apache/tomcat/util/modeler/BaseModelMBean.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
}
|
||||
83
java/org/apache/tomcat/util/modeler/FeatureInfo.java
Normal file
83
java/org/apache/tomcat/util/modeler/FeatureInfo.java
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
17
java/org/apache/tomcat/util/modeler/LocalStrings.properties
Normal file
17
java/org/apache/tomcat/util/modeler/LocalStrings.properties
Normal 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
|
||||
@@ -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
|
||||
@@ -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=ディスクリプタ読み取り中のエラー
|
||||
@@ -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들을 읽는 중 오류 발생
|
||||
@@ -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=读取描述文件出错
|
||||
586
java/org/apache/tomcat/util/modeler/ManagedBean.java
Normal file
586
java/org/apache/tomcat/util/modeler/ManagedBean.java
Normal file
File diff suppressed because it is too large
Load Diff
156
java/org/apache/tomcat/util/modeler/NotificationInfo.java
Normal file
156
java/org/apache/tomcat/util/modeler/NotificationInfo.java
Normal 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();
|
||||
}
|
||||
}
|
||||
172
java/org/apache/tomcat/util/modeler/OperationInfo.java
Normal file
172
java/org/apache/tomcat/util/modeler/OperationInfo.java
Normal 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;
|
||||
}
|
||||
}
|
||||
57
java/org/apache/tomcat/util/modeler/ParameterInfo.java
Normal file
57
java/org/apache/tomcat/util/modeler/ParameterInfo.java
Normal 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;
|
||||
}
|
||||
}
|
||||
748
java/org/apache/tomcat/util/modeler/Registry.java
Normal file
748
java/org/apache/tomcat/util/modeler/Registry.java
Normal file
File diff suppressed because it is too large
Load Diff
120
java/org/apache/tomcat/util/modeler/RegistryMBean.java
Normal file
120
java/org/apache/tomcat/util/modeler/RegistryMBean.java
Normal 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();
|
||||
}
|
||||
34
java/org/apache/tomcat/util/modeler/Util.java
Normal file
34
java/org/apache/tomcat/util/modeler/Util.java
Normal 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;
|
||||
}
|
||||
}
|
||||
247
java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd
Normal file
247
java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd
Normal 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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
59
java/org/apache/tomcat/util/modeler/modules/package.html
Normal file
59
java/org/apache/tomcat/util/modeler/modules/package.html
Normal 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>
|
||||
248
java/org/apache/tomcat/util/modeler/package.html
Normal file
248
java/org/apache/tomcat/util/modeler/package.html
Normal 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><mbean></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>
|
||||
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE mbeans-descriptors PUBLIC
|
||||
"-//Apache Software Foundation//DTD Model MBeans Configuration File"
|
||||
"http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">
|
||||
|
||||
<mbeans-descriptors>
|
||||
|
||||
<!-- ... other MBean definitions ... -->
|
||||
|
||||
<mbean name="Group"
|
||||
className="org.apache.catalina.mbeans.GroupMBean"
|
||||
description="Group from a user database"
|
||||
domain="Users"
|
||||
group="Group"
|
||||
type="org.apache.catalina.Group">
|
||||
|
||||
<attribute name="description"
|
||||
description="Description of this group"
|
||||
type="java.lang.String"/>
|
||||
|
||||
<attribute name="groupname"
|
||||
description="Group name of this group"
|
||||
type="java.lang.String"/>
|
||||
|
||||
<attribute name="roles"
|
||||
description="MBean Names of roles for this group"
|
||||
type="java.lang.String[]"
|
||||
writeable="false"/>
|
||||
|
||||
<attribute name="users"
|
||||
description="MBean Names of user members of this group"
|
||||
type="java.lang.String[]"
|
||||
writeable="false"/>
|
||||
|
||||
<operation name="addRole"
|
||||
description="Add a new authorized role for this group"
|
||||
impact="ACTION"
|
||||
returnType="void">
|
||||
<parameter name="role"
|
||||
description="Role to be added"
|
||||
type="java.lang.String"/>
|
||||
</operation>
|
||||
|
||||
<operation name="removeRole"
|
||||
description="Remove an old authorized role for this group"
|
||||
impact="ACTION"
|
||||
returnType="void">
|
||||
<parameter name="role"
|
||||
description="Role to be removed"
|
||||
type="java.lang.String"/>
|
||||
</operation>
|
||||
|
||||
<operation name="removeRoles"
|
||||
description="Remove all authorized roles for this group"
|
||||
impact="ACTION"
|
||||
returnType="void">
|
||||
</operation>
|
||||
|
||||
</mbean>
|
||||
|
||||
<!-- ... other MBean definitions ... -->
|
||||
|
||||
</mbeans-descriptors>
|
||||
|
||||
</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>
|
||||
Reference in New Issue
Block a user