Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xwiki.admintools.health.cache;

import org.xwiki.stability.Unstable;

/**
* Holds JMX exposed information of name, eviction limit and size for a single cache.
*
* @version $Id$
* @since 1.3
*/
@Unstable
public class CacheInfo
{
private String cacheName;

private long evictionSize;

private long numberOfEntries;

/**
* Default constructor.
*/
public CacheInfo()
{

}

/**
* {@link #setEvictionSize}.
*
* @return the eviction size
*/
public long getEvictionSize()
{
return evictionSize;
}

/**
* Set the maximum eviction size for the cache. This represents the configured upper limit after which entries may
* be evicted.
*
* @param evictionSize the configured eviction size for the cache
*/
public void setEvictionSize(long evictionSize)
{
this.evictionSize = evictionSize;
}

/**
* {@link #setNumberOfEntries}.
*
* @return the number of entries
*/
public long getNumberOfEntries()
{
return numberOfEntries;
}

/**
* Set the current number of entries stored in the cache.
*
* @param numberOfEntries the current number of cache entries
*/
public void setNumberOfEntries(long numberOfEntries)
{
this.numberOfEntries = numberOfEntries;
}

/**
* {@link #setCacheName}.
*
* @return the cache name
*/
public String getCacheName()
{
return cacheName;
}

/**
* Set the name of the cache.
*
* @param cacheName name of the cache
*/
public void setCacheName(String cacheName)
{
this.cacheName = cacheName;
}

/**
* Get a formatted display of the cache load level, expressed as numberOfEntries/evictionSize.
*
* @return a formatted display of the cache size
*/
public String getFormattedCacheSize()
{
return String.format("%d/%d", numberOfEntries, evictionSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;

import org.xwiki.rest.XWikiRestComponent;
Expand Down Expand Up @@ -74,16 +75,49 @@ public interface AdminToolsResource extends XWikiRestComponent
*
* @param attachReference the reference of the attachment.
* @param jobId a unique id for the job.
* @return HTML status code 202 to hint that the upload job has started;
* Return status code 102 if the job already exists and is in progress;
* Return status code 401 if the user does not have admin rights;
* Return status code 500 if there is any error.
* @return HTML status code 202 to hint that the upload job has started; Return status code 102 if the job already
* exists and is in progress; Return status code 401 if the user does not have admin rights; Return status code
* 500 if there is any error.
* @throws XWikiRestException if an error occurred while creating the job, or if the user lacks admin rights.
* @since 1.1
*/
@POST
@Path("/upload")
@Unstable
Response uploadPackageArchive(@QueryParam("attach") String attachReference,
@QueryParam("jobId") String jobId) throws XWikiRestException;
default Response uploadPackageArchive(@QueryParam("attach") String attachReference,
@QueryParam("jobId") String jobId) throws XWikiRestException
{
throw new WebApplicationException(501);
}

/**
* Flush all JMX managed caches.
*
* @return the status of the operation
* @throws XWikiRestException if an error occurred while flushing the cache
* @since 1.3
*/
@POST
@Path("/flushCache/jmx")
@Unstable
default Response flushJMXCache() throws XWikiRestException
{
throw new WebApplicationException(501);
}

/**
* Flush a single JMX managed cache identified by its name.
*
* @param cacheName the name of the cache to flush
* @return the status of the operation
* @throws XWikiRestException if an error occurred while flushing the cache
* @since 1.3
*/
@POST
@Path("/flushCache/jmx/cache")
@Unstable
default Response flushJMXEntryCache(@QueryParam("cacheName") String cacheName) throws XWikiRestException
{
throw new WebApplicationException(501);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,16 @@ public SolrDocumentList getEmptyDocuments(Map<String, String> filters, String or
{
return this.instanceUsageManager.getEmptyDocuments(filters, order);
}

/**
* Check if the used server is compatible with Admin tools installation.
*
* @return a {@code true} if the used server is compatible with the application installation, or {@code false}
* otherwise.
* @since 1.0
*/
public boolean isUsedServerCompatible()
{
return currentServer.getCurrentServer() != null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xwiki.admintools.internal.health.cache;

import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.management.JMException;
import javax.management.ObjectName;

import org.xwiki.component.annotation.Component;

import com.xwiki.admintools.health.cache.CacheInfo;
import com.xwiki.admintools.internal.health.cache.data.CacheDataGenerator;

import groovy.jmx.GroovyMBean;

/**
* Manager class that handles JMX managed cache operations.
*
* @version $Id$
* @since 1.3
*/
@Component(roles = CacheManager.class)
@Singleton
public class CacheManager
{
@Inject
private CacheDataGenerator cacheDataGenerator;

/**
* Get a sorted and filtered {@code List} with the JMX managed caches.
*
* @param filter used to filter caches by name
* @param order the sort order applied to the result, based on the number of entries
* @return a sorted and filtered {@code List} with the JMX managed caches
* @throws JMException if there are any errors during {@link ObjectName} or {@link GroovyMBean} creation
* @throws IOException if there are any errors during the {@link GroovyMBean} creation
*/
public List<CacheInfo> getJMXCaches(String filter, String order) throws JMException, IOException
{
List<CacheInfo> cacheEntries = cacheDataGenerator.getCacheEntries(filter);
return getSortedAndFilteredCacheEntries(cacheEntries, order);
}

/**
* Get detailed statistics for a specific cache.
*
* @param name cache name to be searched for
* @return a {@link Map} with the detailed statistics
* @throws JMException if there are any errors during {@link ObjectName} or {@link GroovyMBean} creation
* @throws IOException if there are any errors during the {@link GroovyMBean} creation
*/
public Map<String, Object> getCacheDetailedView(String name) throws JMException, IOException
{
return cacheDataGenerator.getDetailedCacheEntry(name);
}

private List<CacheInfo> getSortedAndFilteredCacheEntries(List<CacheInfo> cacheEntries, String order)
{

boolean descending = order.equals("desc");
return cacheEntries.stream().sorted(
descending ? Comparator.comparingLong(CacheInfo::getNumberOfEntries).reversed()
: Comparator.comparingLong(CacheInfo::getNumberOfEntries)).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xwiki.admintools.internal.health.cache;

import java.io.IOException;
import java.lang.management.ManagementFactory;

import javax.inject.Singleton;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.xwiki.component.annotation.Component;

import groovy.jmx.GroovyMBean;

/**
* Utility class used to access JMX MBeans.
*
* @version $Id$
* @since 1.3
*/
@Component(roles = GroovyMBeanUtil.class)
@Singleton
public class GroovyMBeanUtil
{
private MBeanServer mBeanServer;

/**
* Return {@link MBeanServer}.
*
* @return the platform MBean server
*/
public MBeanServer getMBeanServer()
{
if (mBeanServer == null) {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
return mBeanServer;
}

/**
* Create a {@link GroovyMBean} wrapper for a given {@link ObjectName}.
*
* @param objectName the JMX object name identifying the MBean
* @return a {@link GroovyMBean} instance for the given object name
*/
public GroovyMBean getGroovyMBean(ObjectName objectName) throws JMException, IOException
{
return new GroovyMBean(getMBeanServer(), objectName);
}
}
Loading