Restructure 'bootstrap' to use 'zero'
parent
d039822064
commit
261955c50b
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.audit;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A value object representing an audit event: at a particular time, a particular user or
|
||||
* agent carried out an action of a particular type. This object records the details of
|
||||
* such an event.
|
||||
*
|
||||
* <p>
|
||||
* Users can inject a {@link AuditEventRepository} to publish their own events or
|
||||
* alternatively use Springs {@link AuthenticationEventPublisher} (usually obtained by
|
||||
* implementing {@link ApplicationEventPublisherAware}).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see AuditEventRepository
|
||||
*/
|
||||
public class AuditEvent implements Serializable {
|
||||
|
||||
private final Date timestamp;
|
||||
|
||||
private final String principal;
|
||||
|
||||
private final String type;
|
||||
|
||||
private final Map<String, Object> data;
|
||||
|
||||
/**
|
||||
* Create a new audit event for the current time.
|
||||
* @param principal The user principal responsible
|
||||
* @param type the event type
|
||||
* @param data The event data
|
||||
*/
|
||||
public AuditEvent(String principal, String type, Map<String, Object> data) {
|
||||
this(new Date(), principal, type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new audit event for the current time from data provided as name-value
|
||||
* pairs
|
||||
* @param principal The user principal responsible
|
||||
* @param type the event type
|
||||
* @param data The event data in the form 'key=value' or simply 'key'
|
||||
*/
|
||||
public AuditEvent(String principal, String type, String... data) {
|
||||
this(new Date(), principal, type, convert(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new audit event.
|
||||
* @param timestamp The date/time of the event
|
||||
* @param principal The user principal responsible
|
||||
* @param type the event type
|
||||
* @param data The event data
|
||||
*/
|
||||
public AuditEvent(Date timestamp, String principal, String type,
|
||||
Map<String, Object> data) {
|
||||
Assert.notNull(timestamp, "Timestamp must not be null");
|
||||
Assert.notNull(type, "Type must not be null");
|
||||
this.timestamp = timestamp;
|
||||
this.principal = principal;
|
||||
this.type = type;
|
||||
this.data = Collections.unmodifiableMap(data);
|
||||
}
|
||||
|
||||
private static Map<String, Object> convert(String[] data) {
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
for (String entry : data) {
|
||||
if (entry.contains("=")) {
|
||||
int index = entry.indexOf("=");
|
||||
result.put(entry.substring(0, index), entry.substring(index + 1));
|
||||
} else {
|
||||
result.put(entry, null);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date/time that the even was logged.
|
||||
*/
|
||||
public Date getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user principal responsible for the event or {@code null}.
|
||||
*/
|
||||
public String getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of event.
|
||||
*/
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event data.
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AuditEvent [timestamp=" + this.timestamp + ", principal="
|
||||
+ this.principal + ", type=" + this.type + ", data=" + this.data + "]";
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.audit;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repository for {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface AuditEventRepository {
|
||||
|
||||
/**
|
||||
* Find audit events relating to the specified principal since the time provided.
|
||||
*
|
||||
* @param principal the principal name to search for
|
||||
* @param after timestamp of earliest result required
|
||||
* @return audit events relating to the principal
|
||||
*/
|
||||
List<AuditEvent> find(String principal, Date after);
|
||||
|
||||
/**
|
||||
* Log an event.
|
||||
*
|
||||
* @param event the audit event to log
|
||||
*/
|
||||
void add(AuditEvent event);
|
||||
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.audit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* In-memory {@link AuditEventRepository} implementation.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class InMemoryAuditEventRepository implements AuditEventRepository {
|
||||
|
||||
private int capacity = 100;
|
||||
|
||||
private Map<String, List<AuditEvent>> events = new HashMap<String, List<AuditEvent>>();
|
||||
|
||||
/**
|
||||
* @param capacity the capacity to set
|
||||
*/
|
||||
public void setCapacity(int capacity) {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuditEvent> find(String principal, Date after) {
|
||||
synchronized (this.events) {
|
||||
return Collections.unmodifiableList(getEvents(principal));
|
||||
}
|
||||
}
|
||||
|
||||
private List<AuditEvent> getEvents(String principal) {
|
||||
if (!this.events.containsKey(principal)) {
|
||||
this.events.put(principal, new ArrayList<AuditEvent>());
|
||||
}
|
||||
return this.events.get(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(AuditEvent event) {
|
||||
synchronized (this.events) {
|
||||
List<AuditEvent> list = getEvents(event.getPrincipal());
|
||||
while (list.size() >= this.capacity) {
|
||||
list.remove(0);
|
||||
}
|
||||
list.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.audit.listener;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.bootstrap.actuate.audit.AuditEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Spring {@link ApplicationEvent} to encapsulate {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuditApplicationEvent extends ApplicationEvent {
|
||||
|
||||
private AuditEvent auditEvent;
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps a newly created
|
||||
* {@link AuditEvent}.
|
||||
* @see AuditEvent#AuditEvent(String, String, Map)
|
||||
*/
|
||||
public AuditApplicationEvent(String principal, String type, Map<String, Object> data) {
|
||||
this(new AuditEvent(principal, type, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps a newly created
|
||||
* {@link AuditEvent}.
|
||||
* @see AuditEvent#AuditEvent(String, String, String...)
|
||||
*/
|
||||
public AuditApplicationEvent(String principal, String type, String... data) {
|
||||
this(new AuditEvent(principal, type, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps a newly created
|
||||
* {@link AuditEvent}.
|
||||
* @see AuditEvent#AuditEvent(Date, String, String, Map)
|
||||
*/
|
||||
public AuditApplicationEvent(Date timestamp, String principal, String type,
|
||||
Map<String, Object> data) {
|
||||
this(new AuditEvent(timestamp, principal, type, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps the specified
|
||||
* {@link AuditEvent}.
|
||||
* @param auditEvent the source of this event
|
||||
*/
|
||||
public AuditApplicationEvent(AuditEvent auditEvent) {
|
||||
super(auditEvent);
|
||||
Assert.notNull(auditEvent, "AuditEvent must not be null");
|
||||
this.auditEvent = auditEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the audit event
|
||||
*/
|
||||
public AuditEvent getAuditEvent() {
|
||||
return this.auditEvent;
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.audit.listener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.bootstrap.actuate.audit.AuditEvent;
|
||||
import org.springframework.bootstrap.actuate.audit.AuditEventRepository;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
/**
|
||||
* {@link ApplicationListener} that listens for {@link AuditEvent}s and stores them in a
|
||||
* {@link AuditEventRepository}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuditListener implements ApplicationListener<AuditApplicationEvent> {
|
||||
|
||||
private static Log logger = LogFactory.getLog(AuditListener.class);
|
||||
|
||||
private final AuditEventRepository auditEventRepository;
|
||||
|
||||
public AuditListener(AuditEventRepository auditEventRepository) {
|
||||
this.auditEventRepository = auditEventRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AuditApplicationEvent event) {
|
||||
logger.info(event.getAuditEvent());
|
||||
this.auditEventRepository.add(event.getAuditEvent());
|
||||
}
|
||||
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.actuate.audit.AuditEvent;
|
||||
import org.springframework.bootstrap.actuate.audit.AuditEventRepository;
|
||||
import org.springframework.bootstrap.actuate.audit.InMemoryAuditEventRepository;
|
||||
import org.springframework.bootstrap.actuate.audit.listener.AuditListener;
|
||||
import org.springframework.bootstrap.actuate.security.AuthenticationAuditListener;
|
||||
import org.springframework.bootstrap.actuate.security.AuthorizationAuditListener;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
public class AuditAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private AuditEventRepository auditEventRepository = new InMemoryAuditEventRepository();
|
||||
|
||||
@Bean
|
||||
public AuditListener auditListener() throws Exception {
|
||||
return new AuditListener(this.auditEventRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.security.authentication.event.AbstractAuthenticationEvent")
|
||||
public AuthenticationAuditListener authenticationAuditListener() throws Exception {
|
||||
return new AuthenticationAuditListener();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.security.access.event.AbstractAuthorizationEvent")
|
||||
public AuthorizationAuditListener authorizationAuditListener() throws Exception {
|
||||
return new AuthorizationAuditListener();
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean(AuditEventRepository.class)
|
||||
protected static class AuditEventRepositoryConfiguration {
|
||||
@Bean
|
||||
public AuditEventRepository auditEventRepository() throws Exception {
|
||||
return new InMemoryAuditEventRepository();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.bootstrap.actuate.endpoint.BeansEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.DumpEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.Endpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.HealthEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.InfoEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.MetricsEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.PublicMetrics;
|
||||
import org.springframework.bootstrap.actuate.endpoint.ShutdownEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.TraceEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.VanillaPublicMetrics;
|
||||
import org.springframework.bootstrap.actuate.health.HealthIndicator;
|
||||
import org.springframework.bootstrap.actuate.health.VanillaHealthIndicator;
|
||||
import org.springframework.bootstrap.actuate.metrics.InMemoryMetricRepository;
|
||||
import org.springframework.bootstrap.actuate.metrics.MetricRepository;
|
||||
import org.springframework.bootstrap.actuate.trace.InMemoryTraceRepository;
|
||||
import org.springframework.bootstrap.actuate.trace.TraceRepository;
|
||||
import org.springframework.bootstrap.bind.PropertiesConfigurationFactory;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for common management
|
||||
* {@link Endpoint}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
public class EndpointAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private HealthIndicator<? extends Object> healthIndicator = new VanillaHealthIndicator();
|
||||
|
||||
@Autowired
|
||||
private InfoPropertiesConfiguration properties;
|
||||
|
||||
@Autowired(required = false)
|
||||
private MetricRepository metricRepository = new InMemoryMetricRepository();
|
||||
|
||||
@Autowired(required = false)
|
||||
private PublicMetrics metrics;
|
||||
|
||||
@Autowired(required = false)
|
||||
private TraceRepository traceRepository = new InMemoryTraceRepository();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EnvironmentEndpoint environmentEndpoint() {
|
||||
return new EnvironmentEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HealthEndpoint<Object> healthEndpoint() {
|
||||
return new HealthEndpoint<Object>(this.healthIndicator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BeansEndpoint beansEndpoint() {
|
||||
return new BeansEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public InfoEndpoint infoEndpoint() throws Exception {
|
||||
LinkedHashMap<String, Object> info = new LinkedHashMap<String, Object>();
|
||||
info.putAll(this.properties.infoMap());
|
||||
GitInfo gitInfo = this.properties.gitInfo();
|
||||
if (gitInfo.getBranch() != null) {
|
||||
info.put("git", gitInfo);
|
||||
}
|
||||
return new InfoEndpoint(info);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MetricsEndpoint metricsEndpoint() {
|
||||
if (this.metrics == null) {
|
||||
this.metrics = new VanillaPublicMetrics(this.metricRepository);
|
||||
}
|
||||
return new MetricsEndpoint(this.metrics);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceEndpoint traceEndpoint() {
|
||||
return new TraceEndpoint(this.traceRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DumpEndpoint dumpEndpoint() {
|
||||
return new DumpEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ShutdownEndpoint shutdownEndpoint() {
|
||||
return new ShutdownEndpoint();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class InfoPropertiesConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
|
||||
@Value("${spring.git.properties:classpath:git.properties}")
|
||||
private Resource gitProperties;
|
||||
|
||||
public GitInfo gitInfo() throws Exception {
|
||||
PropertiesConfigurationFactory<GitInfo> factory = new PropertiesConfigurationFactory<GitInfo>(
|
||||
new GitInfo());
|
||||
factory.setTargetName("git");
|
||||
Properties properties = new Properties();
|
||||
if (this.gitProperties.exists()) {
|
||||
properties = PropertiesLoaderUtils.loadProperties(this.gitProperties);
|
||||
}
|
||||
factory.setProperties(properties);
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
public Map<String, Object> infoMap() throws Exception {
|
||||
PropertiesConfigurationFactory<Map<String, Object>> factory = new PropertiesConfigurationFactory<Map<String, Object>>(
|
||||
new LinkedHashMap<String, Object>());
|
||||
factory.setTargetName("info");
|
||||
factory.setPropertySources(this.environment.getPropertySources());
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class GitInfo {
|
||||
private String branch;
|
||||
private Commit commit = new Commit();
|
||||
|
||||
public String getBranch() {
|
||||
return this.branch;
|
||||
}
|
||||
|
||||
public void setBranch(String branch) {
|
||||
this.branch = branch;
|
||||
}
|
||||
|
||||
public Commit getCommit() {
|
||||
return this.commit;
|
||||
}
|
||||
|
||||
public static class Commit {
|
||||
private String id;
|
||||
private String time;
|
||||
|
||||
public String getId() {
|
||||
return this.id == null ? "" : (this.id.length() > 7 ? this.id.substring(
|
||||
0, 7) : this.id);
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
public void setTime(String time) {
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.actuate.endpoint.Endpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.mvc.EndpointHandlerAdapter;
|
||||
import org.springframework.bootstrap.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.bootstrap.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.bootstrap.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.bootstrap.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
import org.springframework.bootstrap.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.bootstrap.properties.ServerProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} to enable Spring MVC to handle
|
||||
* {@link Endpoint} requests. If the {@link ManagementServerProperties} specifies a
|
||||
* different port to {@link ServerProperties} a new child context is created, otherwise it
|
||||
* is assumed that endpoint requests will be mapped and handled via an already registered
|
||||
* {@link DispatcherServlet}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
||||
@AutoConfigureAfter({ PropertyPlaceholderAutoConfiguration.class,
|
||||
EmbeddedServletContainerAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
ManagementServerPropertiesAutoConfiguration.class })
|
||||
public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private static final Integer DISABLED_PORT = Integer.valueOf(0);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ServerProperties serverProperties = new ServerProperties();
|
||||
|
||||
@Autowired(required = false)
|
||||
private ManagementServerProperties managementServerProperties = new ManagementServerProperties();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointHandlerMapping endpointHandlerMapping() {
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping();
|
||||
mapping.setDisabled(ManagementServerPort.get(this.applicationContext) != ManagementServerPort.SAME);
|
||||
mapping.setPrefix(this.managementServerProperties.getContextPath());
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointHandlerAdapter endpointHandlerAdapter() {
|
||||
return new EndpointHandlerAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (event.getApplicationContext() == this.applicationContext) {
|
||||
if (ManagementServerPort.get(this.applicationContext) == ManagementServerPort.DIFFERENT) {
|
||||
createChildManagementContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createChildManagementContext() {
|
||||
|
||||
final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
childContext.setParent(this.applicationContext);
|
||||
childContext.setId(this.applicationContext.getId() + ":management");
|
||||
|
||||
// Register the ManagementServerChildContextConfiguration first followed
|
||||
// by various specific AutoConfiguration classes. NOTE: The child context
|
||||
// is intentionally not completely auto-configured.
|
||||
childContext.register(EndpointWebMvcChildContextConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
EmbeddedServletContainerAutoConfiguration.class);
|
||||
|
||||
// Ensure close on the parent also closes the child
|
||||
if (this.applicationContext instanceof ConfigurableApplicationContext) {
|
||||
((ConfigurableApplicationContext) this.applicationContext)
|
||||
.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {
|
||||
@Override
|
||||
public void onApplicationEvent(ContextClosedEvent event) {
|
||||
if (event.getApplicationContext() == EndpointWebMvcAutoConfiguration.this.applicationContext) {
|
||||
childContext.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
childContext.refresh();
|
||||
}
|
||||
|
||||
private enum ManagementServerPort {
|
||||
|
||||
DISABLE, SAME, DIFFERENT;
|
||||
|
||||
public static ManagementServerPort get(BeanFactory beanFactory) {
|
||||
|
||||
ServerProperties serverProperties;
|
||||
try {
|
||||
serverProperties = beanFactory.getBean(ServerProperties.class);
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
serverProperties = new ServerProperties();
|
||||
}
|
||||
|
||||
ManagementServerProperties managementServerProperties;
|
||||
try {
|
||||
managementServerProperties = beanFactory
|
||||
.getBean(ManagementServerProperties.class);
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
managementServerProperties = new ManagementServerProperties();
|
||||
}
|
||||
|
||||
if (DISABLED_PORT.equals(managementServerProperties.getPort())) {
|
||||
return DISABLE;
|
||||
}
|
||||
return managementServerProperties.getPort() == null
|
||||
|| serverProperties.getPort() == managementServerProperties.getPort() ? SAME
|
||||
: DIFFERENT;
|
||||
}
|
||||
};
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.actuate.endpoint.mvc.EndpointHandlerAdapter;
|
||||
import org.springframework.bootstrap.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.bootstrap.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnBean;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* Configuration for triggered from {@link EndpointWebMvcAutoConfiguration} when a new
|
||||
* {@link EmbeddedServletContainer} running on a different port is required.
|
||||
*
|
||||
* @see EndpointWebMvcAutoConfiguration
|
||||
*/
|
||||
@Configuration
|
||||
public class EndpointWebMvcChildContextConfiguration implements
|
||||
EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Autowired
|
||||
private ManagementServerProperties managementServerProperties;
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
factory.setPort(this.managementServerProperties.getPort());
|
||||
factory.setAddress(this.managementServerProperties.getAddress());
|
||||
factory.setContextPath(this.managementServerProperties.getContextPath());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DispatcherServlet dispatcherServlet() {
|
||||
DispatcherServlet dispatcherServlet = new DispatcherServlet();
|
||||
|
||||
// Ensure the parent configuration does not leak down to us
|
||||
dispatcherServlet.setDetectAllHandlerAdapters(false);
|
||||
dispatcherServlet.setDetectAllHandlerExceptionResolvers(false);
|
||||
dispatcherServlet.setDetectAllHandlerMappings(false);
|
||||
dispatcherServlet.setDetectAllViewResolvers(false);
|
||||
|
||||
return dispatcherServlet;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerMapping handlerMapping() {
|
||||
return new EndpointHandlerMapping();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerAdapter handlerAdapter() {
|
||||
return new EndpointHandlerAdapter();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass({ EnableWebSecurity.class, Filter.class })
|
||||
public static class EndpointWebMvcChildContextSecurityConfiguration {
|
||||
|
||||
// FIXME reuse of security filter here is not good. What if totally different
|
||||
// security config is required. Perhaps we can just drop it on the management
|
||||
// port?
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(name = "springSecurityFilterChain")
|
||||
public Filter springSecurityFilterChain(HierarchicalBeanFactory beanFactory) {
|
||||
BeanFactory parent = beanFactory.getParentBeanFactory();
|
||||
return parent.getBean("springSecurityFilterChain", Filter.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.bootstrap.actuate.web.BasicErrorController;
|
||||
import org.springframework.bootstrap.actuate.web.ErrorController;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.bootstrap.context.embedded.ErrorPage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} to render errors via a MVC error
|
||||
* controller.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
||||
public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Value("${error.path:/error}")
|
||||
private String errorPath = "/error";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ErrorController.class)
|
||||
public BasicErrorController basicErrorController() {
|
||||
return new BasicErrorController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
factory.addErrorPages(new ErrorPage(this.errorPath));
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.bootstrap.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.bootstrap.autoconfigure.web.ServerPropertiesAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.annotation.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for the
|
||||
* {@link ManagementServerPropertiesAutoConfiguration} bean.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(ServerPropertiesAutoConfiguration.class)
|
||||
@EnableConfigurationProperties
|
||||
public class ManagementServerPropertiesAutoConfiguration {
|
||||
|
||||
@Bean(name = "org.springframework.bootstrap.actuate.properties.ManagementServerProperties")
|
||||
@ConditionalOnMissingBean
|
||||
public ManagementServerProperties serverProperties() {
|
||||
return new ManagementServerProperties();
|
||||
}
|
||||
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.actuate.metrics.CounterService;
|
||||
import org.springframework.bootstrap.actuate.metrics.GaugeService;
|
||||
import org.springframework.bootstrap.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnBean;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} that records Servlet interactions
|
||||
* with a {@link CounterService} and {@link GaugeService}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean({ CounterService.class, GaugeService.class })
|
||||
@ConditionalOnClass({ Servlet.class })
|
||||
@AutoConfigureAfter(MetricRepositoryAutoConfiguration.class)
|
||||
public class MetricFilterAutoConfiguration {
|
||||
|
||||
private static final int UNDEFINED_HTTP_STATUS = 999;
|
||||
|
||||
@Autowired
|
||||
private CounterService counterService;
|
||||
|
||||
@Autowired
|
||||
private GaugeService gaugeService;
|
||||
|
||||
@Bean
|
||||
public Filter metricFilter() {
|
||||
return new MetricsFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter that counts requests and measures processing times.
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
private final class MetricsFilter extends GenericFilterBean {
|
||||
|
||||
// FIXME parameterize the order (ideally it runs before any other filter)
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
if ((request instanceof HttpServletRequest)
|
||||
&& (response instanceof HttpServletResponse)) {
|
||||
doFilter((HttpServletRequest) request, (HttpServletResponse) response,
|
||||
chain);
|
||||
} else {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilter(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
UrlPathHelper helper = new UrlPathHelper();
|
||||
String suffix = helper.getPathWithinApplication(request);
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
try {
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
stopWatch.stop();
|
||||
String gaugeKey = getKey("response" + suffix);
|
||||
MetricFilterAutoConfiguration.this.gaugeService.set(gaugeKey,
|
||||
stopWatch.getTotalTimeMillis());
|
||||
String counterKey = getKey("status." + getStatus(response) + suffix);
|
||||
MetricFilterAutoConfiguration.this.counterService.increment(counterKey);
|
||||
}
|
||||
}
|
||||
|
||||
private int getStatus(HttpServletResponse response) {
|
||||
try {
|
||||
return response.getStatus();
|
||||
} catch (Exception e) {
|
||||
return UNDEFINED_HTTP_STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
private String getKey(String string) {
|
||||
// graphite compatible metric names
|
||||
String value = string.replace("/", ".");
|
||||
value = value.replace("..", ".");
|
||||
if (value.endsWith(".")) {
|
||||
value = value + "root";
|
||||
}
|
||||
if (value.startsWith("_")) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.bootstrap.actuate.metrics.CounterService;
|
||||
import org.springframework.bootstrap.actuate.metrics.DefaultCounterService;
|
||||
import org.springframework.bootstrap.actuate.metrics.DefaultGaugeService;
|
||||
import org.springframework.bootstrap.actuate.metrics.GaugeService;
|
||||
import org.springframework.bootstrap.actuate.metrics.InMemoryMetricRepository;
|
||||
import org.springframework.bootstrap.actuate.metrics.MetricRepository;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for metrics services.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
public class MetricRepositoryAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CounterService counterService() {
|
||||
return new DefaultCounterService(metricRepository());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public GaugeService gaugeService() {
|
||||
return new DefaultGaugeService(metricRepository());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
protected MetricRepository metricRepository() {
|
||||
return new InMemoryMetricRepository();
|
||||
}
|
||||
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.actuate.endpoint.Endpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.bootstrap.actuate.properties.SecurityProperties;
|
||||
import org.springframework.bootstrap.actuate.web.ErrorController;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.annotation.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for security of a web application or
|
||||
* service. By default everything is secured with HTTP Basic authentication except the
|
||||
* {@link SecurityProperties#getIgnored() explicitly ignored} paths (defaults to
|
||||
* <code>/css/**, /js/**, /images/**, /**/favicon.ico</code>
|
||||
* ). Many aspects of the behavior can be controller with {@link SecurityProperties} via
|
||||
* externalized application properties (or via an bean definition of that type to set the
|
||||
* defaults). The user details for authentication are just placeholders
|
||||
* <code>(username=user,
|
||||
* password=password)</code> but can easily be customized by providing a bean definition
|
||||
* of type {@link AuthenticationManager}. Also provides audit logging of authentication
|
||||
* events.
|
||||
*
|
||||
* <p>
|
||||
* The framework {@link Endpoint}s (used to expose application information to operations)
|
||||
* include a {@link Endpoint#isSensitive() sensitive} configuration option which will be
|
||||
* used as a security hint by the filter created here.
|
||||
*
|
||||
* <p>
|
||||
* Some common simple customizations:
|
||||
* <ul>
|
||||
* <li>Switch off security completely and permanently: remove Spring Security from the
|
||||
* classpath or {@link EnableAutoConfiguration#exclude() exclude} this configuration.</li>
|
||||
* <li>Switch off security temporarily (e.g. for a dev environment): set
|
||||
* <code>security.basic.enabled: false</code></li>
|
||||
* <li>Customize the user details: add an AuthenticationManager bean</li>
|
||||
* <li>Add form login for user facing resources: add a
|
||||
* {@link WebSecurityConfigurerAdapter} and use {@link HttpSecurity#formLogin()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ EnableWebSecurity.class })
|
||||
@EnableWebSecurity
|
||||
@EnableConfigurationProperties
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
@Bean(name = "org.springframework.bootstrap.actuate.properties.SecurityProperties")
|
||||
@ConditionalOnMissingBean
|
||||
public SecurityProperties securityProperties() {
|
||||
return new SecurityProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AuthenticationEventPublisher authenticationEventPublisher() {
|
||||
return new DefaultAuthenticationEventPublisher();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean({ BoostrapWebSecurityConfigurerAdapter.class })
|
||||
public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter() {
|
||||
return new BoostrapWebSecurityConfigurerAdapter();
|
||||
}
|
||||
|
||||
// Give user-supplied filters a chance to be last in line
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 10)
|
||||
private static class BoostrapWebSecurityConfigurerAdapter extends
|
||||
WebSecurityConfigurerAdapter {
|
||||
|
||||
private static final String[] NO_PATHS = new String[0];
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties security;
|
||||
|
||||
@Autowired(required = false)
|
||||
private EndpointHandlerMapping endpointHandlerMapping;
|
||||
|
||||
@Autowired
|
||||
private AuthenticationEventPublisher authenticationEventPublisher;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ErrorController errorController;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
if (this.security.isRequireSsl()) {
|
||||
http.requiresChannel().anyRequest().requiresSecure();
|
||||
}
|
||||
|
||||
if (this.security.getBasic().isEnabled()) {
|
||||
String[] paths = getSecurePaths();
|
||||
http.exceptionHandling().authenticationEntryPoint(entryPoint()).and()
|
||||
.requestMatchers().antMatchers(paths);
|
||||
http.httpBasic().and().anonymous().disable();
|
||||
http.authorizeUrls().anyRequest()
|
||||
.hasRole(this.security.getBasic().getRole());
|
||||
}
|
||||
|
||||
// No cookies for service endpoints by default
|
||||
http.sessionManagement().sessionCreationPolicy(this.security.getSessions());
|
||||
}
|
||||
|
||||
private String[] getSecurePaths() {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (String path : this.security.getBasic().getPath()) {
|
||||
path = (path == null ? "" : path.trim());
|
||||
if (path.equals("/**")) {
|
||||
return new String[] { path };
|
||||
}
|
||||
if (!path.equals("")) {
|
||||
list.add(path);
|
||||
}
|
||||
}
|
||||
// FIXME makes more sense to secure endpoints with a different role
|
||||
list.addAll(Arrays.asList(getEndpointPaths(true)));
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
private AuthenticationEntryPoint entryPoint() {
|
||||
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
|
||||
entryPoint.setRealmName(this.security.getBasic().getRealm());
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity builder) throws Exception {
|
||||
IgnoredRequestConfigurer ignoring = builder.ignoring();
|
||||
ignoring.antMatchers(this.security.getIgnored());
|
||||
ignoring.antMatchers(getEndpointPaths(false));
|
||||
if (this.errorController != null) {
|
||||
ignoring.antMatchers(this.errorController.getErrorPath());
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getEndpointPaths(boolean secure) {
|
||||
if (this.endpointHandlerMapping == null) {
|
||||
return NO_PATHS;
|
||||
}
|
||||
|
||||
// FIXME this will still open up paths on the server when a management port is
|
||||
// being used.
|
||||
|
||||
List<Endpoint<?>> endpoints = this.endpointHandlerMapping.getEndpoints();
|
||||
List<String> paths = new ArrayList<String>(endpoints.size());
|
||||
for (Endpoint<?> endpoint : endpoints) {
|
||||
if (endpoint.isSensitive() == secure) {
|
||||
paths.add(endpoint.getPath());
|
||||
}
|
||||
}
|
||||
return paths.toArray(new String[paths.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
AuthenticationManager manager = super.authenticationManager();
|
||||
if (manager instanceof ProviderManager) {
|
||||
((ProviderManager) manager)
|
||||
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean(AuthenticationManager.class)
|
||||
@Configuration
|
||||
public static class AuthenticationManagerConfiguration {
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() throws Exception {
|
||||
return new AuthenticationManagerBuilder().inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and().and()
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.bootstrap.actuate.trace.InMemoryTraceRepository;
|
||||
import org.springframework.bootstrap.actuate.trace.TraceRepository;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link TraceRepository tracing}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
public class TraceRepositoryAutoConfiguration {
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
public TraceRepository traceRepository() {
|
||||
return new InMemoryTraceRepository();
|
||||
}
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.bootstrap.actuate.trace.TraceRepository;
|
||||
import org.springframework.bootstrap.actuate.trace.WebRequestTraceFilter;
|
||||
import org.springframework.bootstrap.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link WebRequestTraceFilter
|
||||
* tracing}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
||||
@AutoConfigureAfter(TraceRepositoryAutoConfiguration.class)
|
||||
public class TraceWebFilterAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private TraceRepository traceRepository;
|
||||
|
||||
@Value("${management.dump_requests:false}")
|
||||
private boolean dumpRequests;
|
||||
|
||||
@Bean
|
||||
public WebRequestTraceFilter webRequestLoggingFilter(BeanFactory beanFactory) {
|
||||
WebRequestTraceFilter filter = new WebRequestTraceFilter(this.traceRepository);
|
||||
filter.setDumpRequests(this.dumpRequests);
|
||||
return filter;
|
||||
}
|
||||
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Abstract base for {@link Endpoint} implementations.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
||||
|
||||
private static final MediaType[] NO_MEDIA_TYPES = new MediaType[0];
|
||||
|
||||
@NotNull
|
||||
@Pattern(regexp = "/[^/]*", message = "Path must start with /")
|
||||
private String path;
|
||||
|
||||
private boolean sensitive;
|
||||
|
||||
public AbstractEndpoint(String path) {
|
||||
this(path, true);
|
||||
}
|
||||
|
||||
public AbstractEndpoint(String path, boolean sensitive) {
|
||||
this.path = path;
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType[] getProduces() {
|
||||
return NO_MEDIA_TYPES;
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
/**
|
||||
* Tagging interface used to indicate that {@link Endpoint} that performs some action.
|
||||
* Allows mappings to refine the types of request supported.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface ActionEndpoint<T> extends Endpoint<T> {
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.support.LiveBeansView;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Exposes JSON view of Spring beans. If the {@link Environment} contains a key setting
|
||||
* the {@link LiveBeansView#MBEAN_DOMAIN_PROPERTY_NAME} then all application contexts in
|
||||
* the JVM will be shown (and the corresponding MBeans will be registered per the standard
|
||||
* behavior of LiveBeansView). Otherwise only the current application context.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.beans", ignoreUnknownFields = false)
|
||||
public class BeansEndpoint extends AbstractEndpoint<String> implements
|
||||
ApplicationContextAware {
|
||||
|
||||
private LiveBeansView liveBeansView = new LiveBeansView();
|
||||
|
||||
public BeansEndpoint() {
|
||||
super("/beans");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
if (context.getEnvironment()
|
||||
.getProperty(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME) == null) {
|
||||
this.liveBeansView.setApplicationContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType[] getProduces() {
|
||||
return new MediaType[] { MediaType.APPLICATION_JSON };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String invoke() {
|
||||
return this.liveBeansView.getSnapshotAsJson();
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose thread info.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.dump", ignoreUnknownFields = false)
|
||||
public class DumpEndpoint extends AbstractEndpoint<List<ThreadInfo>> {
|
||||
|
||||
/**
|
||||
* Create a new {@link DumpEndpoint} instance.
|
||||
*/
|
||||
public DumpEndpoint() {
|
||||
super("/dump");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThreadInfo> invoke() {
|
||||
return Arrays.asList(ManagementFactory.getThreadMXBean().dumpAllThreads(true,
|
||||
true));
|
||||
}
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* An endpoint that can be used to expose useful information to operations. Usually
|
||||
* exposed via Spring MVC but could also be exposed using some other technique.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface Endpoint<T> {
|
||||
|
||||
/**
|
||||
* Returns the path of the endpoint. Must start with '/' and should not include
|
||||
* wildcards.
|
||||
*/
|
||||
String getPath();
|
||||
|
||||
/**
|
||||
* Returns if the endpoint is sensitive, i.e. may return data that the average user
|
||||
* should not see. Mappings can use this as a security hint.
|
||||
*/
|
||||
boolean isSensitive();
|
||||
|
||||
/**
|
||||
* Returns the {@link MediaType}s that this endpoint produces or {@code null}.
|
||||
*/
|
||||
MediaType[] getProduces();
|
||||
|
||||
/**
|
||||
* Called to invoke the endpoint.
|
||||
* @return the results of the invocation
|
||||
*/
|
||||
T invoke();
|
||||
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link ConfigurableEnvironment environment} information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.env", ignoreUnknownFields = false)
|
||||
public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
||||
EnvironmentAware {
|
||||
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Create a new {@link EnvironmentEndpoint} instance.
|
||||
*/
|
||||
public EnvironmentEndpoint() {
|
||||
super("/env");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
for (PropertySource<?> source : getPropertySources()) {
|
||||
if (source instanceof EnumerablePropertySource) {
|
||||
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
for (String name : enumerable.getPropertyNames()) {
|
||||
map.put(name, sanitize(name, enumerable.getProperty(name)));
|
||||
}
|
||||
result.put(source.getName(), map);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Iterable<PropertySource<?>> getPropertySources() {
|
||||
if (this.environment != null
|
||||
&& this.environment instanceof ConfigurableEnvironment) {
|
||||
return ((ConfigurableEnvironment) this.environment).getPropertySources();
|
||||
}
|
||||
return new StandardEnvironment().getPropertySources();
|
||||
}
|
||||
|
||||
private Object sanitize(String name, Object object) {
|
||||
if (name.toLowerCase().endsWith("password")
|
||||
|| name.toLowerCase().endsWith("secret")) {
|
||||
return object == null ? null : "******";
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import org.springframework.bootstrap.actuate.health.HealthIndicator;
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose application health.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.health", ignoreUnknownFields = false)
|
||||
public class HealthEndpoint<T> extends AbstractEndpoint<T> {
|
||||
|
||||
private HealthIndicator<? extends T> indicator;
|
||||
|
||||
/**
|
||||
* Create a new {@link HealthIndicator} instance.
|
||||
*
|
||||
* @param indicator the health indicator
|
||||
*/
|
||||
public HealthEndpoint(HealthIndicator<? extends T> indicator) {
|
||||
super("/health", false);
|
||||
Assert.notNull(indicator, "Indicator must not be null");
|
||||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T invoke() {
|
||||
return this.indicator.health();
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose arbitrary application information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.info", ignoreUnknownFields = false)
|
||||
public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private Map<String, ? extends Object> info;
|
||||
|
||||
/**
|
||||
* Create a new {@link InfoEndpoint} instance.
|
||||
*
|
||||
* @param info the info to expose
|
||||
*/
|
||||
public InfoEndpoint(Map<String, ? extends Object> info) {
|
||||
super("/info", true);
|
||||
Assert.notNull(info, "Info must not be null");
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>(this.info);
|
||||
info.putAll(getAdditionalInfo());
|
||||
return info;
|
||||
}
|
||||
|
||||
protected Map<String, Object> getAdditionalInfo() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.bootstrap.actuate.metrics.Metric;
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link PublicMetrics}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.metrics", ignoreUnknownFields = false)
|
||||
public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private PublicMetrics metrics;
|
||||
|
||||
/**
|
||||
* Create a new {@link MetricsEndpoint} instance.
|
||||
*
|
||||
* @param metrics the metrics to expose
|
||||
*/
|
||||
public MetricsEndpoint(PublicMetrics metrics) {
|
||||
super("/metrics");
|
||||
Assert.notNull(metrics, "Metrics must not be null");
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
for (Metric metric : this.metrics.metrics()) {
|
||||
result.put(metric.getName(), metric.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.bootstrap.actuate.metrics.Metric;
|
||||
|
||||
/**
|
||||
* Interface to expose specific {@link Metric}s via a {@link MetricsEndpoint}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see VanillaPublicMetrics
|
||||
*/
|
||||
public interface PublicMetrics {
|
||||
|
||||
/**
|
||||
* @return an indication of current state through metrics
|
||||
*/
|
||||
Collection<Metric> metrics();
|
||||
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* {@link ActionEndpoint} to shutdown the {@link ApplicationContext}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.shutdown", ignoreUnknownFields = false)
|
||||
public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
||||
ApplicationContextAware, ActionEndpoint<Map<String, Object>> {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ManagementServerProperties configuration = new ManagementServerProperties();
|
||||
|
||||
/**
|
||||
* Create a new {@link ShutdownEndpoint} instance.
|
||||
*/
|
||||
public ShutdownEndpoint() {
|
||||
super("/shutdown");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
if (this.configuration == null || !this.configuration.isAllowShutdown()
|
||||
|| this.context == null) {
|
||||
return Collections.<String, Object> singletonMap("message",
|
||||
"Shutdown not enabled, sorry.");
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(500L);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
ShutdownEndpoint.this.context.close();
|
||||
}
|
||||
}).start();
|
||||
|
||||
return Collections.<String, Object> singletonMap("message",
|
||||
"Shutting down, bye...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
if (context instanceof ConfigurableApplicationContext) {
|
||||
this.context = (ConfigurableApplicationContext) context;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.bootstrap.actuate.trace.Trace;
|
||||
import org.springframework.bootstrap.actuate.trace.TraceRepository;
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link Trace} information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.trace", ignoreUnknownFields = false)
|
||||
public class TraceEndpoint extends AbstractEndpoint<List<Trace>> {
|
||||
|
||||
private TraceRepository repository;
|
||||
|
||||
/**
|
||||
* Create a new {@link TraceEndpoint} instance.
|
||||
*
|
||||
* @param repository the trace repository
|
||||
*/
|
||||
public TraceEndpoint(TraceRepository repository) {
|
||||
super("/trace");
|
||||
Assert.notNull(repository, "Repository must not be null");
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Trace> invoke() {
|
||||
return this.repository.findAll();
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import org.springframework.bootstrap.actuate.metrics.Metric;
|
||||
import org.springframework.bootstrap.actuate.metrics.MetricRepository;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link PublicMetrics} that exposes all metrics from the
|
||||
* {@link MetricRepository} along with memory information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VanillaPublicMetrics implements PublicMetrics {
|
||||
|
||||
private MetricRepository metricRepository;
|
||||
|
||||
public VanillaPublicMetrics(MetricRepository metricRepository) {
|
||||
Assert.notNull(metricRepository, "MetricRepository must not be null");
|
||||
this.metricRepository = metricRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Metric> metrics() {
|
||||
Collection<Metric> result = new LinkedHashSet<Metric>(
|
||||
this.metricRepository.findAll());
|
||||
result.add(new Metric("mem", new Long(Runtime.getRuntime().totalMemory()) / 1024));
|
||||
result.add(new Metric("mem.free",
|
||||
new Long(Runtime.getRuntime().freeMemory()) / 1024));
|
||||
result.add(new Metric("processors", Runtime.getRuntime().availableProcessors()));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.bootstrap.actuate.endpoint.Endpoint;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor;
|
||||
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
/**
|
||||
* MVC {@link HandlerAdapter} for {@link Endpoint}s. Similar in may respects to
|
||||
* {@link AbstractMessageConverterMethodProcessor} but not tied to annotated methods.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see EndpointHandlerMapping
|
||||
*/
|
||||
public class EndpointHandlerAdapter implements HandlerAdapter {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(EndpointHandlerAdapter.class);
|
||||
|
||||
private static final MediaType MEDIA_TYPE_APPLICATION = new MediaType("application");
|
||||
|
||||
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
|
||||
|
||||
private List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
private List<MediaType> allSupportedMediaTypes;
|
||||
|
||||
public EndpointHandlerAdapter() {
|
||||
WebMvcConfigurationSupportConventions conventions = new WebMvcConfigurationSupportConventions();
|
||||
setMessageConverters(conventions.getDefaultHttpMessageConverters());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Object handler) {
|
||||
return handler instanceof Endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified(HttpServletRequest request, Object handler) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
handle(request, response, (Endpoint<?>) handler);
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
Endpoint<?> endpoint) throws Exception {
|
||||
|
||||
Object result = endpoint.invoke();
|
||||
Class<?> resultClass = result.getClass();
|
||||
|
||||
List<MediaType> mediaTypes = getMediaTypes(request, endpoint, resultClass);
|
||||
MediaType selectedMediaType = selectMediaType(mediaTypes);
|
||||
|
||||
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
|
||||
try {
|
||||
if (selectedMediaType != null) {
|
||||
selectedMediaType = selectedMediaType.removeQualityValue();
|
||||
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
|
||||
if (messageConverter.canWrite(resultClass, selectedMediaType)) {
|
||||
((HttpMessageConverter<Object>) messageConverter).write(result,
|
||||
selectedMediaType, outputMessage);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Written [" + result + "] as \""
|
||||
+ selectedMediaType + "\" using [" + messageConverter
|
||||
+ "]");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
|
||||
} finally {
|
||||
outputMessage.close();
|
||||
}
|
||||
}
|
||||
|
||||
private List<MediaType> getMediaTypes(HttpServletRequest request,
|
||||
Endpoint<?> endpoint, Class<?> resultClass)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
List<MediaType> requested = getAcceptableMediaTypes(request);
|
||||
List<MediaType> producible = getProducibleMediaTypes(endpoint, resultClass);
|
||||
|
||||
Set<MediaType> compatible = new LinkedHashSet<MediaType>();
|
||||
for (MediaType r : requested) {
|
||||
for (MediaType p : producible) {
|
||||
if (r.isCompatibleWith(p)) {
|
||||
compatible.add(getMostSpecificMediaType(r, p));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (compatible.isEmpty()) {
|
||||
throw new HttpMediaTypeNotAcceptableException(producible);
|
||||
}
|
||||
List<MediaType> mediaTypes = new ArrayList<MediaType>(compatible);
|
||||
MediaType.sortBySpecificityAndQuality(mediaTypes);
|
||||
return mediaTypes;
|
||||
}
|
||||
|
||||
private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
List<MediaType> mediaTypes = this.contentNegotiationManager
|
||||
.resolveMediaTypes(new ServletWebRequest(request));
|
||||
return mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL)
|
||||
: mediaTypes;
|
||||
}
|
||||
|
||||
private List<MediaType> getProducibleMediaTypes(Endpoint<?> endpoint,
|
||||
Class<?> returnValueClass) {
|
||||
MediaType[] mediaTypes = endpoint.getProduces();
|
||||
if (mediaTypes != null && mediaTypes.length != 0) {
|
||||
return Arrays.asList(mediaTypes);
|
||||
}
|
||||
|
||||
if (this.allSupportedMediaTypes.isEmpty()) {
|
||||
return Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
|
||||
List<MediaType> result = new ArrayList<MediaType>();
|
||||
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||
if (converter.canWrite(returnValueClass, null)) {
|
||||
result.addAll(converter.getSupportedMediaTypes());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
||||
produceType = produceType.copyQualityValue(acceptType);
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) <= 0 ? acceptType
|
||||
: produceType;
|
||||
}
|
||||
|
||||
private MediaType selectMediaType(List<MediaType> mediaTypes) {
|
||||
MediaType selectedMediaType = null;
|
||||
for (MediaType mediaType : mediaTypes) {
|
||||
if (mediaType.isConcrete()) {
|
||||
selectedMediaType = mediaType;
|
||||
break;
|
||||
} else if (mediaType.equals(MediaType.ALL)
|
||||
|| mediaType.equals(MEDIA_TYPE_APPLICATION)) {
|
||||
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return selectedMediaType;
|
||||
}
|
||||
|
||||
public void setContentNegotiationManager(
|
||||
ContentNegotiationManager contentNegotiationManager) {
|
||||
this.contentNegotiationManager = contentNegotiationManager;
|
||||
}
|
||||
|
||||
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||
this.messageConverters = messageConverters;
|
||||
Set<MediaType> allSupportedMediaTypes = new LinkedHashSet<MediaType>();
|
||||
for (HttpMessageConverter<?> messageConverter : messageConverters) {
|
||||
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
|
||||
}
|
||||
this.allSupportedMediaTypes = new ArrayList<MediaType>(allSupportedMediaTypes);
|
||||
MediaType.sortBySpecificity(this.allSupportedMediaTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default conventions, taken from {@link WebMvcConfigurationSupport} with a few minor
|
||||
* tweaks.
|
||||
*/
|
||||
private static class WebMvcConfigurationSupportConventions extends
|
||||
WebMvcConfigurationSupport {
|
||||
public List<HttpMessageConverter<?>> getDefaultHttpMessageConverters() {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
addDefaultHttpMessageConverters(converters);
|
||||
for (HttpMessageConverter<?> converter : converters) {
|
||||
if (converter instanceof MappingJackson2HttpMessageConverter) {
|
||||
MappingJackson2HttpMessageConverter jacksonConverter = (MappingJackson2HttpMessageConverter) converter;
|
||||
jacksonConverter.getObjectMapper().disable(
|
||||
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
}
|
||||
}
|
||||
return converters;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.bootstrap.actuate.endpoint.ActionEndpoint;
|
||||
import org.springframework.bootstrap.actuate.endpoint.Endpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
|
||||
|
||||
/**
|
||||
* {@link HandlerMapping} to map {@link Endpoint}s to URLs via {@link Endpoint#getPath()}.
|
||||
* Standard {@link Endpoint}s are mapped to GET requests, {@link ActionEndpoint}s are
|
||||
* mapped to POST requests.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see EndpointHandlerAdapter
|
||||
*/
|
||||
public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||
InitializingBean, ApplicationContextAware {
|
||||
|
||||
private List<Endpoint<?>> endpoints;
|
||||
|
||||
private String prefix = "";
|
||||
|
||||
private boolean disabled = false;
|
||||
|
||||
/**
|
||||
* Create a new {@link EndpointHandlerMapping} instance. All {@link Endpoint}s will be
|
||||
* detected from the {@link ApplicationContext}.
|
||||
*/
|
||||
public EndpointHandlerMapping() {
|
||||
setOrder(HIGHEST_PRECEDENCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link EndpointHandlerMapping} with the specified endpoints.
|
||||
* @param endpoints the endpoints
|
||||
*/
|
||||
public EndpointHandlerMapping(Collection<? extends Endpoint<?>> endpoints) {
|
||||
Assert.notNull(endpoints, "Endpoints must not be null");
|
||||
this.endpoints = new ArrayList<Endpoint<?>>(endpoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (this.endpoints == null) {
|
||||
this.endpoints = findEndpointBeans();
|
||||
}
|
||||
if (!this.disabled) {
|
||||
for (Endpoint<?> endpoint : this.endpoints) {
|
||||
registerHandler(this.prefix + endpoint.getPath(), endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private List<Endpoint<?>> findEndpointBeans() {
|
||||
return new ArrayList(BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
getApplicationContext(), Endpoint.class).values());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object lookupHandler(String urlPath, HttpServletRequest request)
|
||||
throws Exception {
|
||||
Object handler = super.lookupHandler(urlPath, request);
|
||||
if (handler != null) {
|
||||
Object endpoint = (handler instanceof HandlerExecutionChain ? ((HandlerExecutionChain) handler)
|
||||
.getHandler() : handler);
|
||||
String method = (endpoint instanceof ActionEndpoint<?> ? "POST" : "GET");
|
||||
if (request.getMethod().equals(method)) {
|
||||
return endpoint;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prefix the prefix to set
|
||||
*/
|
||||
public void setPrefix(String prefix) {
|
||||
Assert.isTrue("".equals(prefix) || StringUtils.startsWithIgnoreCase(prefix, "/"),
|
||||
"prefix must start with '/'");
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if this mapping is disabled.
|
||||
*/
|
||||
public void setDisabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this mapping is disabled.
|
||||
*/
|
||||
public boolean isDisabled() {
|
||||
return this.disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the endpoints
|
||||
*/
|
||||
public List<Endpoint<?>> getEndpoints() {
|
||||
return Collections.unmodifiableList(this.endpoints);
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.fixme;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.bootstrap.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.bootstrap.actuate.web.BasicErrorController;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnBean;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.ErrorPage;
|
||||
import org.springframework.bootstrap.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
* Configuration for creating a new container (e.g. tomcat) for the management endpoints.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@Import(ManagementSecurityConfiguration.class)
|
||||
public class ManagementServerConfiguration {
|
||||
|
||||
// FIXME delete when security works
|
||||
|
||||
@Bean
|
||||
public DispatcherServlet dispatcherServlet() {
|
||||
return new DispatcherServlet();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(
|
||||
ApplicationContext context) {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BasicErrorController errorEndpoint() {
|
||||
return new BasicErrorController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(TomcatEmbeddedServletContainerFactory.class)
|
||||
public EmbeddedServletContainerFactory tomcatContainer(
|
||||
HierarchicalBeanFactory beanFactory) {
|
||||
TomcatEmbeddedServletContainerFactory factory = beanFactory
|
||||
.getParentBeanFactory().getBean(
|
||||
TomcatEmbeddedServletContainerFactory.class);
|
||||
return factory.getChildContextFactory("Management");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(JettyEmbeddedServletContainerFactory.class)
|
||||
public EmbeddedServletContainerFactory jettyContainer() {
|
||||
return new JettyEmbeddedServletContainerFactory();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class ServerCustomizationConfiguration implements
|
||||
EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Value("${endpoints.error.path:/error}")
|
||||
private String errorPath = "/error";
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext beanFactory;
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
ManagementServerProperties configuration = this.beanFactory
|
||||
.getBean(ManagementServerProperties.class);
|
||||
factory.setPort(configuration.getPort());
|
||||
factory.setAddress(configuration.getAddress());
|
||||
factory.setContextPath(configuration.getContextPath());
|
||||
factory.addErrorPages(new ErrorPage(this.errorPath));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(name = {
|
||||
"org.springframework.security.config.annotation.web.EnableWebSecurity",
|
||||
"javax.servlet.Filter" })
|
||||
class ManagementSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
// TODO: enable and get rid of the empty filter when @ConditionalOnBean works
|
||||
// @ConditionalOnBean(name = "springSecurityFilterChain")
|
||||
public Filter springSecurityFilterChain(HierarchicalBeanFactory beanFactory) {
|
||||
BeanFactory parent = beanFactory.getParentBeanFactory();
|
||||
if (parent != null && parent.containsBean("springSecurityFilterChain")) {
|
||||
return parent.getBean("springSecurityFilterChain", Filter.class);
|
||||
}
|
||||
return new GenericFilterBean() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.health;
|
||||
|
||||
/**
|
||||
* Strategy interface used to provide an indication of application health.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see VanillaHealthIndicator
|
||||
*/
|
||||
public interface HealthIndicator<T> {
|
||||
|
||||
/**
|
||||
* @return an indication of health
|
||||
*/
|
||||
T health();
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.health;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link HealthIndicator} that simply returns "ok".
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VanillaHealthIndicator implements HealthIndicator<String> {
|
||||
|
||||
@Override
|
||||
public String health() {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
/**
|
||||
* A service that can be used to increment, decrement and reset a {@link Metric}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface CounterService {
|
||||
|
||||
/**
|
||||
* Increment the specified metric by 1.
|
||||
* @param metricName the name of the metric
|
||||
*/
|
||||
void increment(String metricName);
|
||||
|
||||
/**
|
||||
* Decrement the specified metric by 1.
|
||||
* @param metricName the name of the metric
|
||||
*/
|
||||
void decrement(String metricName);
|
||||
|
||||
/**
|
||||
* Reset the specified metric to 0.
|
||||
* @param metricName the name of the metric
|
||||
*/
|
||||
void reset(String metricName);
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link CounterService}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class DefaultCounterService implements CounterService {
|
||||
|
||||
private MetricRepository repository;
|
||||
|
||||
/**
|
||||
* Create a {@link DefaultCounterService} instance.
|
||||
* @param repository the underlying repository used to manage metrics
|
||||
*/
|
||||
public DefaultCounterService(MetricRepository repository) {
|
||||
super();
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(String metricName) {
|
||||
this.repository.increment(wrap(metricName), 1, new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrement(String metricName) {
|
||||
this.repository.increment(wrap(metricName), -1, new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(String metricName) {
|
||||
this.repository.set(wrap(metricName), 0, new Date());
|
||||
}
|
||||
|
||||
private String wrap(String metricName) {
|
||||
if (metricName.startsWith("counter")) {
|
||||
return metricName;
|
||||
} else {
|
||||
return "counter." + metricName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link GaugeService}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class DefaultGaugeService implements GaugeService {
|
||||
|
||||
private MetricRepository metricRepository;
|
||||
|
||||
/**
|
||||
* @param counterRepository
|
||||
*/
|
||||
public DefaultGaugeService(MetricRepository counterRepository) {
|
||||
super();
|
||||
this.metricRepository = counterRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String metricName, double value) {
|
||||
this.metricRepository.set(wrap(metricName), value, new Date());
|
||||
}
|
||||
|
||||
private String wrap(String metricName) {
|
||||
if (metricName.startsWith("gauge")) {
|
||||
return metricName;
|
||||
} else {
|
||||
return "gauge." + metricName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
/**
|
||||
* A service that can be used to manage a {@link Metric} as a gauge.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface GaugeService {
|
||||
|
||||
/**
|
||||
* Set the specified metric value
|
||||
* @param metricName the metric to set
|
||||
* @param value the value of the metric
|
||||
*/
|
||||
void set(String metricName, double value);
|
||||
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class InMemoryMetricRepository implements MetricRepository {
|
||||
|
||||
private ConcurrentMap<String, Measurement> metrics = new ConcurrentHashMap<String, Measurement>();
|
||||
|
||||
@Override
|
||||
public void increment(String metricName, int amount, Date timestamp) {
|
||||
// FIXME this might not be thread safe
|
||||
Measurement current = this.metrics.get(metricName);
|
||||
if (current != null) {
|
||||
Metric metric = current.getMetric();
|
||||
this.metrics.replace(metricName, current,
|
||||
new Measurement(timestamp, metric.increment(amount)));
|
||||
} else {
|
||||
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric(
|
||||
metricName, amount)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String metricName, double value, Date timestamp) {
|
||||
Measurement current = this.metrics.get(metricName);
|
||||
if (current != null) {
|
||||
Metric metric = current.getMetric();
|
||||
this.metrics.replace(metricName, current,
|
||||
new Measurement(timestamp, metric.set(value)));
|
||||
} else {
|
||||
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric(
|
||||
metricName, value)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String metricName) {
|
||||
this.metrics.remove(metricName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metric findOne(String metricName) {
|
||||
if (this.metrics.containsKey(metricName)) {
|
||||
return this.metrics.get(metricName).getMetric();
|
||||
}
|
||||
return new Metric(metricName, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Metric> findAll() {
|
||||
ArrayList<Metric> result = new ArrayList<Metric>();
|
||||
for (Measurement measurement : this.metrics.values()) {
|
||||
result.add(measurement.getMetric());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A {@link Metric} at a given point in time.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public final class Measurement {
|
||||
|
||||
private Date timestamp;
|
||||
|
||||
private Metric metric;
|
||||
|
||||
public Measurement(Date timestamp, Metric metric) {
|
||||
this.timestamp = timestamp;
|
||||
this.metric = metric;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
public Metric getMetric() {
|
||||
return this.metric;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Measurement [dateTime=" + this.timestamp + ", metric=" + this.metric
|
||||
+ "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.timestamp);
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.metric);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() == obj.getClass()) {
|
||||
Measurement other = (Measurement) obj;
|
||||
boolean result = ObjectUtils.nullSafeEquals(this.timestamp, other.timestamp);
|
||||
result &= ObjectUtils.nullSafeEquals(this.metric, other.metric);
|
||||
return result;
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Immutable class that can be used to hold any arbitrary system measurement value. For
|
||||
* example a metric might record the number of active connections.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see MetricRepository
|
||||
* @see CounterService
|
||||
*/
|
||||
public final class Metric {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final double value;
|
||||
|
||||
/**
|
||||
* Create a new {@link Metric} instance.
|
||||
* @param name the name of the metric
|
||||
* @param value the value of the metric
|
||||
*/
|
||||
public Metric(String name, double value) {
|
||||
super();
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the metric.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the metric.
|
||||
*/
|
||||
public double getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Metric} with an incremented value.
|
||||
* @param amount the amount that the new metric will differ from this one
|
||||
* @return a new {@link Metric} instance
|
||||
*/
|
||||
public Metric increment(int amount) {
|
||||
return new Metric(this.name, new Double(((int) this.value) + amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Metric} with a different value.
|
||||
* @param value the value of the new metric
|
||||
* @return a new {@link Metric} instance
|
||||
*/
|
||||
public Metric set(double value) {
|
||||
return new Metric(this.name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Metric [name=" + this.name + ", value=" + this.value + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int valueHashCode = ObjectUtils.hashCode(this.value);
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
result = prime * result + (valueHashCode ^ (valueHashCode >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() == obj.getClass()) {
|
||||
Metric other = (Metric) obj;
|
||||
boolean result = ObjectUtils.nullSafeEquals(this.name, other.name);
|
||||
result &= Double.doubleToLongBits(this.value) == Double
|
||||
.doubleToLongBits(other.value);
|
||||
return result;
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.metrics;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* A Repository used to manage {@link Metric}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface MetricRepository {
|
||||
|
||||
// FIXME perhaps revisit this, there is no way to get timestamps
|
||||
// could also simply, leaving increment to counter service
|
||||
|
||||
// Perhaps findAll, findOne should return Measurements
|
||||
// put(String name, Callback -> process(Metric)
|
||||
|
||||
void increment(String metricName, int amount, Date timestamp);
|
||||
|
||||
void set(String metricName, double value, Date timestamp);
|
||||
|
||||
void delete(String metricName);
|
||||
|
||||
Metric findOne(String metricName);
|
||||
|
||||
Collection<Metric> findAll();
|
||||
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.properties;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.bootstrap.properties.ServerProperties;
|
||||
|
||||
/**
|
||||
* Properties for the management server (e.g. port and path settings).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see ServerProperties
|
||||
*/
|
||||
@ConfigurationProperties(name = "management", ignoreUnknownFields = false)
|
||||
public class ManagementServerProperties {
|
||||
|
||||
private Integer port;
|
||||
|
||||
private InetAddress address;
|
||||
|
||||
@NotNull
|
||||
private String contextPath = "";
|
||||
|
||||
private boolean allowShutdown = false;
|
||||
|
||||
public boolean isAllowShutdown() {
|
||||
return this.allowShutdown;
|
||||
}
|
||||
|
||||
public void setAllowShutdown(boolean allowShutdown) {
|
||||
this.allowShutdown = allowShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the management port or {@code null} if the
|
||||
* {@link ServerProperties#getPort() server port} should be used.
|
||||
* @see #setPort(Integer)
|
||||
*/
|
||||
public Integer getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the port of the management server, use {@code null} if the
|
||||
* {@link ServerProperties#getPort() server port} should be used. To disable use 0.
|
||||
*/
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public InetAddress getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public void setAddress(InetAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getContextPath() {
|
||||
return this.contextPath;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.properties;
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.security.config.annotation.web.configurers.SessionCreationPolicy;
|
||||
|
||||
/**
|
||||
* Properties for the security aspects of an application.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "security", ignoreUnknownFields = false)
|
||||
public class SecurityProperties {
|
||||
|
||||
private boolean requireSsl;
|
||||
|
||||
private Basic basic = new Basic();
|
||||
|
||||
private SessionCreationPolicy sessions = SessionCreationPolicy.stateless;
|
||||
|
||||
private String[] ignored = new String[] { "/css/**", "/js/**", "/images/**",
|
||||
"/**/favicon.ico" };
|
||||
|
||||
public SessionCreationPolicy getSessions() {
|
||||
return this.sessions;
|
||||
}
|
||||
|
||||
public void setSessions(SessionCreationPolicy sessions) {
|
||||
this.sessions = sessions;
|
||||
}
|
||||
|
||||
public Basic getBasic() {
|
||||
return this.basic;
|
||||
}
|
||||
|
||||
public void setBasic(Basic basic) {
|
||||
this.basic = basic;
|
||||
}
|
||||
|
||||
public boolean isRequireSsl() {
|
||||
return this.requireSsl;
|
||||
}
|
||||
|
||||
public void setRequireSsl(boolean requireSsl) {
|
||||
this.requireSsl = requireSsl;
|
||||
}
|
||||
|
||||
public void setIgnored(String... ignored) {
|
||||
this.ignored = ignored;
|
||||
}
|
||||
|
||||
public String[] getIgnored() {
|
||||
return this.ignored;
|
||||
}
|
||||
|
||||
public static class Basic {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
private String realm = "Spring";
|
||||
|
||||
private String[] path = new String[] { "/**" };
|
||||
|
||||
private String role = "USER";
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return this.realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String[] getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String... paths) {
|
||||
this.path = paths;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return this.role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.security;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.bootstrap.actuate.audit.AuditEvent;
|
||||
import org.springframework.bootstrap.actuate.audit.listener.AuditApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
|
||||
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
|
||||
import org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent;
|
||||
|
||||
/**
|
||||
* {@link ApplicationListener} expose Spring Security {@link AbstractAuthenticationEvent
|
||||
* authentication events} as {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuthenticationAuditListener implements
|
||||
ApplicationListener<AbstractAuthenticationEvent>, ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractAuthenticationEvent event) {
|
||||
if (event instanceof AbstractAuthenticationFailureEvent) {
|
||||
onAuthenticationFailureEvent((AbstractAuthenticationFailureEvent) event);
|
||||
} else if (event instanceof AuthenticationSwitchUserEvent) {
|
||||
onAuthenticationSwitchUserEvent((AuthenticationSwitchUserEvent) event);
|
||||
} else {
|
||||
onAuthenticationEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAuthenticationFailureEvent(AbstractAuthenticationFailureEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("type", event.getException().getClass().getName());
|
||||
data.put("message", event.getException().getMessage());
|
||||
publish(new AuditEvent(event.getAuthentication().getName(),
|
||||
"AUTHENTICATION_FAILURE", data));
|
||||
}
|
||||
|
||||
private void onAuthenticationSwitchUserEvent(AuthenticationSwitchUserEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
if (event.getAuthentication().getDetails() != null) {
|
||||
data.put("details", event.getAuthentication().getDetails());
|
||||
}
|
||||
data.put("target", event.getTargetUser().getUsername());
|
||||
publish(new AuditEvent(event.getAuthentication().getName(),
|
||||
"AUTHENTICATION_SWITCH", data));
|
||||
}
|
||||
|
||||
private void onAuthenticationEvent(AbstractAuthenticationEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
if (event.getAuthentication().getDetails() != null) {
|
||||
data.put("details", event.getAuthentication().getDetails());
|
||||
}
|
||||
publish(new AuditEvent(event.getAuthentication().getName(),
|
||||
"AUTHENTICATION_SUCCESS", data));
|
||||
}
|
||||
|
||||
private void publish(AuditEvent event) {
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(new AuditApplicationEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.security;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.bootstrap.actuate.audit.AuditEvent;
|
||||
import org.springframework.bootstrap.actuate.audit.listener.AuditApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.security.access.event.AbstractAuthorizationEvent;
|
||||
import org.springframework.security.access.event.AuthenticationCredentialsNotFoundEvent;
|
||||
import org.springframework.security.access.event.AuthorizationFailureEvent;
|
||||
|
||||
/**
|
||||
* {@link ApplicationListener} expose Spring Security {@link AbstractAuthorizationEvent
|
||||
* authorization events} as {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuthorizationAuditListener implements
|
||||
ApplicationListener<AbstractAuthorizationEvent>, ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractAuthorizationEvent event) {
|
||||
if (event instanceof AuthenticationCredentialsNotFoundEvent) {
|
||||
onAuthenticationCredentialsNotFoundEvent((AuthenticationCredentialsNotFoundEvent) event);
|
||||
} else if (event instanceof AuthorizationFailureEvent) {
|
||||
onAuthorizationFailureEvent((AuthorizationFailureEvent) event);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAuthenticationCredentialsNotFoundEvent(
|
||||
AuthenticationCredentialsNotFoundEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("type", event.getCredentialsNotFoundException().getClass().getName());
|
||||
data.put("message", event.getCredentialsNotFoundException().getMessage());
|
||||
publish(new AuditEvent("<unknown>", "AUTHENTICATION_FAILURE", data));
|
||||
}
|
||||
|
||||
private void onAuthorizationFailureEvent(AuthorizationFailureEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("type", event.getAccessDeniedException().getClass().getName());
|
||||
data.put("message", event.getAccessDeniedException().getMessage());
|
||||
publish(new AuditEvent(event.getAuthentication().getName(),
|
||||
"AUTHORIZATION_FAILURE", data));
|
||||
}
|
||||
|
||||
private void publish(AuditEvent event) {
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(new AuditApplicationEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.trace;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* In-memory implementation of {@link TraceRepository}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class InMemoryTraceRepository implements TraceRepository {
|
||||
|
||||
private int capacity = 100;
|
||||
|
||||
private List<Trace> traces = new ArrayList<Trace>();
|
||||
|
||||
/**
|
||||
* @param capacity the capacity to set
|
||||
*/
|
||||
public void setCapacity(int capacity) {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Trace> findAll() {
|
||||
synchronized (this.traces) {
|
||||
return Collections.unmodifiableList(this.traces);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Map<String, Object> map) {
|
||||
Trace trace = new Trace(new Date(), map);
|
||||
synchronized (this.traces) {
|
||||
while (this.traces.size() >= this.capacity) {
|
||||
this.traces.remove(0);
|
||||
}
|
||||
this.traces.add(trace);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.trace;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A value object representing a trace event: at a particular time with a simple (map)
|
||||
* information. Can be used for analyzing contextual information such as HTTP headers.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public final class Trace {
|
||||
|
||||
private Date timestamp;
|
||||
|
||||
private Map<String, Object> info;
|
||||
|
||||
public Trace(Date timestamp, Map<String, Object> info) {
|
||||
super();
|
||||
Assert.notNull(timestamp, "Timestamp must not be null");
|
||||
Assert.notNull(info, "Info must not be null");
|
||||
this.timestamp = timestamp;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
public Map<String, Object> getInfo() {
|
||||
return this.info;
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.trace;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A repository for {@link Trace}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface TraceRepository {
|
||||
|
||||
/**
|
||||
* Find all {@link Trace} objects contained in the repository.
|
||||
*/
|
||||
List<Trace> findAll();
|
||||
|
||||
/**
|
||||
* Add a new {@link Trace} object at the current time.
|
||||
* @param traceInfo trace information
|
||||
*/
|
||||
void add(Map<String, Object> traceInfo);
|
||||
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.trace;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Servlet {@link Filter} that logs all requests to a {@link TraceRepository}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class WebRequestTraceFilter implements Filter, Ordered {
|
||||
|
||||
final Log logger = LogFactory.getLog(WebRequestTraceFilter.class);
|
||||
|
||||
private boolean dumpRequests = false;
|
||||
|
||||
private final TraceRepository traceRepository;
|
||||
|
||||
private int order = Integer.MAX_VALUE;
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* @param traceRepository
|
||||
*/
|
||||
public WebRequestTraceFilter(TraceRepository traceRepository) {
|
||||
this.traceRepository = traceRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param order the order to set
|
||||
*/
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debugging feature. If enabled, and trace logging is enabled then web request
|
||||
* headers will be logged.
|
||||
*/
|
||||
public void setDumpRequests(boolean dumpRequests) {
|
||||
this.dumpRequests = dumpRequests;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
|
||||
Map<String, Object> trace = getTrace(request);
|
||||
this.traceRepository.add(trace);
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Processing request " + request.getMethod() + " "
|
||||
+ request.getRequestURI());
|
||||
if (this.dumpRequests) {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> headers = (Map<String, Object>) trace
|
||||
.get("headers");
|
||||
this.logger.trace("Headers: "
|
||||
+ this.objectMapper.writeValueAsString(headers));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalStateException("Cannot create JSON", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
protected Map<String, Object> getTrace(HttpServletRequest request) {
|
||||
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
Enumeration<String> names = request.getHeaderNames();
|
||||
|
||||
while (names.hasMoreElements()) {
|
||||
String name = names.nextElement();
|
||||
List<String> values = Collections.list(request.getHeaders(name));
|
||||
Object value = values;
|
||||
if (values.size() == 1) {
|
||||
value = values.get(0);
|
||||
} else if (values.isEmpty()) {
|
||||
value = "";
|
||||
}
|
||||
map.put(name, value);
|
||||
|
||||
}
|
||||
Map<String, Object> trace = new LinkedHashMap<String, Object>();
|
||||
trace.put("method", request.getMethod());
|
||||
trace.put("path", request.getRequestURI());
|
||||
trace.put("headers", map);
|
||||
return trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.web;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.bootstrap.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Basic global error {@link Controller}, rendering servlet container error codes and
|
||||
* messages where available. More specific errors can be handled either using Spring MVC
|
||||
* abstractions (e.g. {@code @ExceptionHandler}) or by adding servlet
|
||||
* {@link AbstractEmbeddedServletContainerFactory#setErrorPages(java.util.Set) container
|
||||
* error pages}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Controller
|
||||
public class BasicErrorController implements ErrorController {
|
||||
|
||||
private Log logger = LogFactory.getLog(BasicErrorController.class);
|
||||
|
||||
@Value("${error.path:/error}")
|
||||
private String errorPath;
|
||||
|
||||
@Override
|
||||
public String getErrorPath() {
|
||||
return this.errorPath;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "${error.path:/error}", produces = "text/html")
|
||||
public ModelAndView errorHtml(HttpServletRequest request) {
|
||||
Map<String, Object> map = error(request);
|
||||
return new ModelAndView("error", map);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "${error.path:/error}")
|
||||
@ResponseBody
|
||||
public Map<String, Object> error(HttpServletRequest request) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
map.put("timestamp", new Date());
|
||||
try {
|
||||
Throwable error = (Throwable) request
|
||||
.getAttribute("javax.servlet.error.exception");
|
||||
Object obj = request.getAttribute("javax.servlet.error.status_code");
|
||||
int status = 999;
|
||||
if (obj != null) {
|
||||
status = (Integer) obj;
|
||||
map.put("error", HttpStatus.valueOf(status).getReasonPhrase());
|
||||
} else {
|
||||
map.put("error", "None");
|
||||
}
|
||||
map.put("status", status);
|
||||
if (error != null) {
|
||||
while (error instanceof ServletException) {
|
||||
error = ((ServletException) error).getCause();
|
||||
}
|
||||
map.put("exception", error.getClass().getName());
|
||||
map.put("message", error.getMessage());
|
||||
String trace = request.getParameter("trace");
|
||||
if (trace != null && !"false".equals(trace.toLowerCase())) {
|
||||
StringWriter stackTrace = new StringWriter();
|
||||
error.printStackTrace(new PrintWriter(stackTrace));
|
||||
stackTrace.flush();
|
||||
map.put("trace", stackTrace.toString());
|
||||
}
|
||||
this.logger.error(error);
|
||||
} else {
|
||||
Object message = request.getAttribute("javax.servlet.error.message");
|
||||
map.put("message", message == null ? "No message available" : message);
|
||||
}
|
||||
return map;
|
||||
} catch (Exception e) {
|
||||
map.put("error", e.getClass().getName());
|
||||
map.put("message", e.getMessage());
|
||||
this.logger.error(e);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.bootstrap.actuate.web;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
/**
|
||||
* Marker interface used to indicate that a {@link Controller @Controller} is used to
|
||||
* render errors.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface ErrorController {
|
||||
|
||||
public String getErrorPath();
|
||||
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.audit;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A value object representing an audit event: at a particular time, a particular user or
|
||||
* agent carried out an action of a particular type. This object records the details of
|
||||
* such an event.
|
||||
*
|
||||
* <p>
|
||||
* Users can inject a {@link AuditEventRepository} to publish their own events or
|
||||
* alternatively use Springs {@link AuthenticationEventPublisher} (usually obtained by
|
||||
* implementing {@link ApplicationEventPublisherAware}).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see AuditEventRepository
|
||||
*/
|
||||
public class AuditEvent implements Serializable {
|
||||
|
||||
private final Date timestamp;
|
||||
|
||||
private final String principal;
|
||||
|
||||
private final String type;
|
||||
|
||||
private final Map<String, Object> data;
|
||||
|
||||
/**
|
||||
* Create a new audit event for the current time.
|
||||
* @param principal The user principal responsible
|
||||
* @param type the event type
|
||||
* @param data The event data
|
||||
*/
|
||||
public AuditEvent(String principal, String type, Map<String, Object> data) {
|
||||
this(new Date(), principal, type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new audit event for the current time from data provided as name-value
|
||||
* pairs
|
||||
* @param principal The user principal responsible
|
||||
* @param type the event type
|
||||
* @param data The event data in the form 'key=value' or simply 'key'
|
||||
*/
|
||||
public AuditEvent(String principal, String type, String... data) {
|
||||
this(new Date(), principal, type, convert(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new audit event.
|
||||
* @param timestamp The date/time of the event
|
||||
* @param principal The user principal responsible
|
||||
* @param type the event type
|
||||
* @param data The event data
|
||||
*/
|
||||
public AuditEvent(Date timestamp, String principal, String type,
|
||||
Map<String, Object> data) {
|
||||
Assert.notNull(timestamp, "Timestamp must not be null");
|
||||
Assert.notNull(type, "Type must not be null");
|
||||
this.timestamp = timestamp;
|
||||
this.principal = principal;
|
||||
this.type = type;
|
||||
this.data = Collections.unmodifiableMap(data);
|
||||
}
|
||||
|
||||
private static Map<String, Object> convert(String[] data) {
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
for (String entry : data) {
|
||||
if (entry.contains("=")) {
|
||||
int index = entry.indexOf("=");
|
||||
result.put(entry.substring(0, index), entry.substring(index + 1));
|
||||
} else {
|
||||
result.put(entry, null);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date/time that the even was logged.
|
||||
*/
|
||||
public Date getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user principal responsible for the event or {@code null}.
|
||||
*/
|
||||
public String getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of event.
|
||||
*/
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event data.
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AuditEvent [timestamp=" + this.timestamp + ", principal="
|
||||
+ this.principal + ", type=" + this.type + ", data=" + this.data + "]";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.audit;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repository for {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface AuditEventRepository {
|
||||
|
||||
/**
|
||||
* Find audit events relating to the specified principal since the time provided.
|
||||
*
|
||||
* @param principal the principal name to search for
|
||||
* @param after timestamp of earliest result required
|
||||
* @return audit events relating to the principal
|
||||
*/
|
||||
List<AuditEvent> find(String principal, Date after);
|
||||
|
||||
/**
|
||||
* Log an event.
|
||||
*
|
||||
* @param event the audit event to log
|
||||
*/
|
||||
void add(AuditEvent event);
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.audit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* In-memory {@link AuditEventRepository} implementation.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class InMemoryAuditEventRepository implements AuditEventRepository {
|
||||
|
||||
private int capacity = 100;
|
||||
|
||||
private Map<String, List<AuditEvent>> events = new HashMap<String, List<AuditEvent>>();
|
||||
|
||||
/**
|
||||
* @param capacity the capacity to set
|
||||
*/
|
||||
public void setCapacity(int capacity) {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuditEvent> find(String principal, Date after) {
|
||||
synchronized (this.events) {
|
||||
return Collections.unmodifiableList(getEvents(principal));
|
||||
}
|
||||
}
|
||||
|
||||
private List<AuditEvent> getEvents(String principal) {
|
||||
if (!this.events.containsKey(principal)) {
|
||||
this.events.put(principal, new ArrayList<AuditEvent>());
|
||||
}
|
||||
return this.events.get(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(AuditEvent event) {
|
||||
synchronized (this.events) {
|
||||
List<AuditEvent> list = getEvents(event.getPrincipal());
|
||||
while (list.size() >= this.capacity) {
|
||||
list.remove(0);
|
||||
}
|
||||
list.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.audit.listener;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.zero.actuate.audit.AuditEvent;
|
||||
|
||||
/**
|
||||
* Spring {@link ApplicationEvent} to encapsulate {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuditApplicationEvent extends ApplicationEvent {
|
||||
|
||||
private AuditEvent auditEvent;
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps a newly created
|
||||
* {@link AuditEvent}.
|
||||
* @see AuditEvent#AuditEvent(String, String, Map)
|
||||
*/
|
||||
public AuditApplicationEvent(String principal, String type, Map<String, Object> data) {
|
||||
this(new AuditEvent(principal, type, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps a newly created
|
||||
* {@link AuditEvent}.
|
||||
* @see AuditEvent#AuditEvent(String, String, String...)
|
||||
*/
|
||||
public AuditApplicationEvent(String principal, String type, String... data) {
|
||||
this(new AuditEvent(principal, type, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps a newly created
|
||||
* {@link AuditEvent}.
|
||||
* @see AuditEvent#AuditEvent(Date, String, String, Map)
|
||||
*/
|
||||
public AuditApplicationEvent(Date timestamp, String principal, String type,
|
||||
Map<String, Object> data) {
|
||||
this(new AuditEvent(timestamp, principal, type, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AuditApplicationEvent} that wraps the specified
|
||||
* {@link AuditEvent}.
|
||||
* @param auditEvent the source of this event
|
||||
*/
|
||||
public AuditApplicationEvent(AuditEvent auditEvent) {
|
||||
super(auditEvent);
|
||||
Assert.notNull(auditEvent, "AuditEvent must not be null");
|
||||
this.auditEvent = auditEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the audit event
|
||||
*/
|
||||
public AuditEvent getAuditEvent() {
|
||||
return this.auditEvent;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.audit.listener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.zero.actuate.audit.AuditEvent;
|
||||
import org.springframework.zero.actuate.audit.AuditEventRepository;
|
||||
|
||||
/**
|
||||
* {@link ApplicationListener} that listens for {@link AuditEvent}s and stores them in a
|
||||
* {@link AuditEventRepository}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuditListener implements ApplicationListener<AuditApplicationEvent> {
|
||||
|
||||
private static Log logger = LogFactory.getLog(AuditListener.class);
|
||||
|
||||
private final AuditEventRepository auditEventRepository;
|
||||
|
||||
public AuditListener(AuditEventRepository auditEventRepository) {
|
||||
this.auditEventRepository = auditEventRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AuditApplicationEvent event) {
|
||||
logger.info(event.getAuditEvent());
|
||||
this.auditEventRepository.add(event.getAuditEvent());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.zero.actuate.audit.AuditEvent;
|
||||
import org.springframework.zero.actuate.audit.AuditEventRepository;
|
||||
import org.springframework.zero.actuate.audit.InMemoryAuditEventRepository;
|
||||
import org.springframework.zero.actuate.audit.listener.AuditListener;
|
||||
import org.springframework.zero.actuate.security.AuthenticationAuditListener;
|
||||
import org.springframework.zero.actuate.security.AuthorizationAuditListener;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
public class AuditAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private AuditEventRepository auditEventRepository = new InMemoryAuditEventRepository();
|
||||
|
||||
@Bean
|
||||
public AuditListener auditListener() throws Exception {
|
||||
return new AuditListener(this.auditEventRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.security.authentication.event.AbstractAuthenticationEvent")
|
||||
public AuthenticationAuditListener authenticationAuditListener() throws Exception {
|
||||
return new AuthenticationAuditListener();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.security.access.event.AbstractAuthorizationEvent")
|
||||
public AuthorizationAuditListener authorizationAuditListener() throws Exception {
|
||||
return new AuthorizationAuditListener();
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean(AuditEventRepository.class)
|
||||
protected static class AuditEventRepositoryConfiguration {
|
||||
@Bean
|
||||
public AuditEventRepository auditEventRepository() throws Exception {
|
||||
return new InMemoryAuditEventRepository();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.zero.actuate.endpoint.BeansEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.DumpEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.Endpoint;
|
||||
import org.springframework.zero.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.HealthEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.InfoEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.MetricsEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.PublicMetrics;
|
||||
import org.springframework.zero.actuate.endpoint.ShutdownEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.TraceEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.VanillaPublicMetrics;
|
||||
import org.springframework.zero.actuate.health.HealthIndicator;
|
||||
import org.springframework.zero.actuate.health.VanillaHealthIndicator;
|
||||
import org.springframework.zero.actuate.metrics.InMemoryMetricRepository;
|
||||
import org.springframework.zero.actuate.metrics.MetricRepository;
|
||||
import org.springframework.zero.actuate.trace.InMemoryTraceRepository;
|
||||
import org.springframework.zero.actuate.trace.TraceRepository;
|
||||
import org.springframework.zero.bind.PropertiesConfigurationFactory;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for common management
|
||||
* {@link Endpoint}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
public class EndpointAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private HealthIndicator<? extends Object> healthIndicator = new VanillaHealthIndicator();
|
||||
|
||||
@Autowired
|
||||
private InfoPropertiesConfiguration properties;
|
||||
|
||||
@Autowired(required = false)
|
||||
private MetricRepository metricRepository = new InMemoryMetricRepository();
|
||||
|
||||
@Autowired(required = false)
|
||||
private PublicMetrics metrics;
|
||||
|
||||
@Autowired(required = false)
|
||||
private TraceRepository traceRepository = new InMemoryTraceRepository();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EnvironmentEndpoint environmentEndpoint() {
|
||||
return new EnvironmentEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HealthEndpoint<Object> healthEndpoint() {
|
||||
return new HealthEndpoint<Object>(this.healthIndicator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BeansEndpoint beansEndpoint() {
|
||||
return new BeansEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public InfoEndpoint infoEndpoint() throws Exception {
|
||||
LinkedHashMap<String, Object> info = new LinkedHashMap<String, Object>();
|
||||
info.putAll(this.properties.infoMap());
|
||||
GitInfo gitInfo = this.properties.gitInfo();
|
||||
if (gitInfo.getBranch() != null) {
|
||||
info.put("git", gitInfo);
|
||||
}
|
||||
return new InfoEndpoint(info);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MetricsEndpoint metricsEndpoint() {
|
||||
if (this.metrics == null) {
|
||||
this.metrics = new VanillaPublicMetrics(this.metricRepository);
|
||||
}
|
||||
return new MetricsEndpoint(this.metrics);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceEndpoint traceEndpoint() {
|
||||
return new TraceEndpoint(this.traceRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DumpEndpoint dumpEndpoint() {
|
||||
return new DumpEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ShutdownEndpoint shutdownEndpoint() {
|
||||
return new ShutdownEndpoint();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class InfoPropertiesConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
|
||||
@Value("${spring.git.properties:classpath:git.properties}")
|
||||
private Resource gitProperties;
|
||||
|
||||
public GitInfo gitInfo() throws Exception {
|
||||
PropertiesConfigurationFactory<GitInfo> factory = new PropertiesConfigurationFactory<GitInfo>(
|
||||
new GitInfo());
|
||||
factory.setTargetName("git");
|
||||
Properties properties = new Properties();
|
||||
if (this.gitProperties.exists()) {
|
||||
properties = PropertiesLoaderUtils.loadProperties(this.gitProperties);
|
||||
}
|
||||
factory.setProperties(properties);
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
public Map<String, Object> infoMap() throws Exception {
|
||||
PropertiesConfigurationFactory<Map<String, Object>> factory = new PropertiesConfigurationFactory<Map<String, Object>>(
|
||||
new LinkedHashMap<String, Object>());
|
||||
factory.setTargetName("info");
|
||||
factory.setPropertySources(this.environment.getPropertySources());
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class GitInfo {
|
||||
private String branch;
|
||||
private Commit commit = new Commit();
|
||||
|
||||
public String getBranch() {
|
||||
return this.branch;
|
||||
}
|
||||
|
||||
public void setBranch(String branch) {
|
||||
this.branch = branch;
|
||||
}
|
||||
|
||||
public Commit getCommit() {
|
||||
return this.commit;
|
||||
}
|
||||
|
||||
public static class Commit {
|
||||
private String id;
|
||||
private String time;
|
||||
|
||||
public String getId() {
|
||||
return this.id == null ? "" : (this.id.length() > 7 ? this.id.substring(
|
||||
0, 7) : this.id);
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
public void setTime(String time) {
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.zero.actuate.endpoint.Endpoint;
|
||||
import org.springframework.zero.actuate.endpoint.mvc.EndpointHandlerAdapter;
|
||||
import org.springframework.zero.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.zero.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.zero.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.zero.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
import org.springframework.zero.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.zero.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.zero.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.zero.properties.ServerProperties;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} to enable Spring MVC to handle
|
||||
* {@link Endpoint} requests. If the {@link ManagementServerProperties} specifies a
|
||||
* different port to {@link ServerProperties} a new child context is created, otherwise it
|
||||
* is assumed that endpoint requests will be mapped and handled via an already registered
|
||||
* {@link DispatcherServlet}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
||||
@AutoConfigureAfter({ PropertyPlaceholderAutoConfiguration.class,
|
||||
EmbeddedServletContainerAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
ManagementServerPropertiesAutoConfiguration.class })
|
||||
public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private static final Integer DISABLED_PORT = Integer.valueOf(0);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ServerProperties serverProperties = new ServerProperties();
|
||||
|
||||
@Autowired(required = false)
|
||||
private ManagementServerProperties managementServerProperties = new ManagementServerProperties();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointHandlerMapping endpointHandlerMapping() {
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping();
|
||||
mapping.setDisabled(ManagementServerPort.get(this.applicationContext) != ManagementServerPort.SAME);
|
||||
mapping.setPrefix(this.managementServerProperties.getContextPath());
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointHandlerAdapter endpointHandlerAdapter() {
|
||||
return new EndpointHandlerAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (event.getApplicationContext() == this.applicationContext) {
|
||||
if (ManagementServerPort.get(this.applicationContext) == ManagementServerPort.DIFFERENT) {
|
||||
createChildManagementContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createChildManagementContext() {
|
||||
|
||||
final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
childContext.setParent(this.applicationContext);
|
||||
childContext.setId(this.applicationContext.getId() + ":management");
|
||||
|
||||
// Register the ManagementServerChildContextConfiguration first followed
|
||||
// by various specific AutoConfiguration classes. NOTE: The child context
|
||||
// is intentionally not completely auto-configured.
|
||||
childContext.register(EndpointWebMvcChildContextConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
EmbeddedServletContainerAutoConfiguration.class);
|
||||
|
||||
// Ensure close on the parent also closes the child
|
||||
if (this.applicationContext instanceof ConfigurableApplicationContext) {
|
||||
((ConfigurableApplicationContext) this.applicationContext)
|
||||
.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {
|
||||
@Override
|
||||
public void onApplicationEvent(ContextClosedEvent event) {
|
||||
if (event.getApplicationContext() == EndpointWebMvcAutoConfiguration.this.applicationContext) {
|
||||
childContext.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
childContext.refresh();
|
||||
}
|
||||
|
||||
private enum ManagementServerPort {
|
||||
|
||||
DISABLE, SAME, DIFFERENT;
|
||||
|
||||
public static ManagementServerPort get(BeanFactory beanFactory) {
|
||||
|
||||
ServerProperties serverProperties;
|
||||
try {
|
||||
serverProperties = beanFactory.getBean(ServerProperties.class);
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
serverProperties = new ServerProperties();
|
||||
}
|
||||
|
||||
ManagementServerProperties managementServerProperties;
|
||||
try {
|
||||
managementServerProperties = beanFactory
|
||||
.getBean(ManagementServerProperties.class);
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
managementServerProperties = new ManagementServerProperties();
|
||||
}
|
||||
|
||||
if (DISABLED_PORT.equals(managementServerProperties.getPort())) {
|
||||
return DISABLE;
|
||||
}
|
||||
return managementServerProperties.getPort() == null
|
||||
|| serverProperties.getPort() == managementServerProperties.getPort() ? SAME
|
||||
: DIFFERENT;
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.zero.actuate.endpoint.mvc.EndpointHandlerAdapter;
|
||||
import org.springframework.zero.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.zero.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnBean;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.zero.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
|
||||
/**
|
||||
* Configuration for triggered from {@link EndpointWebMvcAutoConfiguration} when a new
|
||||
* {@link EmbeddedServletContainer} running on a different port is required.
|
||||
*
|
||||
* @see EndpointWebMvcAutoConfiguration
|
||||
*/
|
||||
@Configuration
|
||||
public class EndpointWebMvcChildContextConfiguration implements
|
||||
EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Autowired
|
||||
private ManagementServerProperties managementServerProperties;
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
factory.setPort(this.managementServerProperties.getPort());
|
||||
factory.setAddress(this.managementServerProperties.getAddress());
|
||||
factory.setContextPath(this.managementServerProperties.getContextPath());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DispatcherServlet dispatcherServlet() {
|
||||
DispatcherServlet dispatcherServlet = new DispatcherServlet();
|
||||
|
||||
// Ensure the parent configuration does not leak down to us
|
||||
dispatcherServlet.setDetectAllHandlerAdapters(false);
|
||||
dispatcherServlet.setDetectAllHandlerExceptionResolvers(false);
|
||||
dispatcherServlet.setDetectAllHandlerMappings(false);
|
||||
dispatcherServlet.setDetectAllViewResolvers(false);
|
||||
|
||||
return dispatcherServlet;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerMapping handlerMapping() {
|
||||
return new EndpointHandlerMapping();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerAdapter handlerAdapter() {
|
||||
return new EndpointHandlerAdapter();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass({ EnableWebSecurity.class, Filter.class })
|
||||
public static class EndpointWebMvcChildContextSecurityConfiguration {
|
||||
|
||||
// FIXME reuse of security filter here is not good. What if totally different
|
||||
// security config is required. Perhaps we can just drop it on the management
|
||||
// port?
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(name = "springSecurityFilterChain")
|
||||
public Filter springSecurityFilterChain(HierarchicalBeanFactory beanFactory) {
|
||||
BeanFactory parent = beanFactory.getParentBeanFactory();
|
||||
return parent.getBean("springSecurityFilterChain", Filter.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.zero.actuate.web.BasicErrorController;
|
||||
import org.springframework.zero.actuate.web.ErrorController;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.zero.context.embedded.ErrorPage;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} to render errors via a MVC error
|
||||
* controller.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
||||
public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Value("${error.path:/error}")
|
||||
private String errorPath = "/error";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ErrorController.class)
|
||||
public BasicErrorController basicErrorController() {
|
||||
return new BasicErrorController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
factory.addErrorPages(new ErrorPage(this.errorPath));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.zero.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.zero.autoconfigure.web.ServerPropertiesAutoConfiguration;
|
||||
import org.springframework.zero.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.zero.context.annotation.EnableConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for the
|
||||
* {@link ManagementServerPropertiesAutoConfiguration} bean.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(ServerPropertiesAutoConfiguration.class)
|
||||
@EnableConfigurationProperties
|
||||
public class ManagementServerPropertiesAutoConfiguration {
|
||||
|
||||
@Bean(name = "org.springframework.zero.actuate.properties.ManagementServerProperties")
|
||||
@ConditionalOnMissingBean
|
||||
public ManagementServerProperties serverProperties() {
|
||||
return new ManagementServerProperties();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.zero.actuate.metrics.CounterService;
|
||||
import org.springframework.zero.actuate.metrics.GaugeService;
|
||||
import org.springframework.zero.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnBean;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} that records Servlet interactions
|
||||
* with a {@link CounterService} and {@link GaugeService}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean({ CounterService.class, GaugeService.class })
|
||||
@ConditionalOnClass({ Servlet.class })
|
||||
@AutoConfigureAfter(MetricRepositoryAutoConfiguration.class)
|
||||
public class MetricFilterAutoConfiguration {
|
||||
|
||||
private static final int UNDEFINED_HTTP_STATUS = 999;
|
||||
|
||||
@Autowired
|
||||
private CounterService counterService;
|
||||
|
||||
@Autowired
|
||||
private GaugeService gaugeService;
|
||||
|
||||
@Bean
|
||||
public Filter metricFilter() {
|
||||
return new MetricsFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter that counts requests and measures processing times.
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
private final class MetricsFilter extends GenericFilterBean {
|
||||
|
||||
// FIXME parameterize the order (ideally it runs before any other filter)
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
if ((request instanceof HttpServletRequest)
|
||||
&& (response instanceof HttpServletResponse)) {
|
||||
doFilter((HttpServletRequest) request, (HttpServletResponse) response,
|
||||
chain);
|
||||
} else {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilter(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
UrlPathHelper helper = new UrlPathHelper();
|
||||
String suffix = helper.getPathWithinApplication(request);
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
try {
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
stopWatch.stop();
|
||||
String gaugeKey = getKey("response" + suffix);
|
||||
MetricFilterAutoConfiguration.this.gaugeService.set(gaugeKey,
|
||||
stopWatch.getTotalTimeMillis());
|
||||
String counterKey = getKey("status." + getStatus(response) + suffix);
|
||||
MetricFilterAutoConfiguration.this.counterService.increment(counterKey);
|
||||
}
|
||||
}
|
||||
|
||||
private int getStatus(HttpServletResponse response) {
|
||||
try {
|
||||
return response.getStatus();
|
||||
} catch (Exception e) {
|
||||
return UNDEFINED_HTTP_STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
private String getKey(String string) {
|
||||
// graphite compatible metric names
|
||||
String value = string.replace("/", ".");
|
||||
value = value.replace("..", ".");
|
||||
if (value.endsWith(".")) {
|
||||
value = value + "root";
|
||||
}
|
||||
if (value.startsWith("_")) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.zero.actuate.metrics.CounterService;
|
||||
import org.springframework.zero.actuate.metrics.DefaultCounterService;
|
||||
import org.springframework.zero.actuate.metrics.DefaultGaugeService;
|
||||
import org.springframework.zero.actuate.metrics.GaugeService;
|
||||
import org.springframework.zero.actuate.metrics.InMemoryMetricRepository;
|
||||
import org.springframework.zero.actuate.metrics.MetricRepository;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for metrics services.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
public class MetricRepositoryAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CounterService counterService() {
|
||||
return new DefaultCounterService(metricRepository());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public GaugeService gaugeService() {
|
||||
return new DefaultGaugeService(metricRepository());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
protected MetricRepository metricRepository() {
|
||||
return new InMemoryMetricRepository();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
import org.springframework.zero.actuate.endpoint.Endpoint;
|
||||
import org.springframework.zero.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.zero.actuate.properties.SecurityProperties;
|
||||
import org.springframework.zero.actuate.web.ErrorController;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.zero.context.annotation.EnableConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for security of a web application or
|
||||
* service. By default everything is secured with HTTP Basic authentication except the
|
||||
* {@link SecurityProperties#getIgnored() explicitly ignored} paths (defaults to
|
||||
* <code>/css/**, /js/**, /images/**, /**/favicon.ico</code>
|
||||
* ). Many aspects of the behavior can be controller with {@link SecurityProperties} via
|
||||
* externalized application properties (or via an bean definition of that type to set the
|
||||
* defaults). The user details for authentication are just placeholders
|
||||
* <code>(username=user,
|
||||
* password=password)</code> but can easily be customized by providing a bean definition
|
||||
* of type {@link AuthenticationManager}. Also provides audit logging of authentication
|
||||
* events.
|
||||
*
|
||||
* <p>
|
||||
* The framework {@link Endpoint}s (used to expose application information to operations)
|
||||
* include a {@link Endpoint#isSensitive() sensitive} configuration option which will be
|
||||
* used as a security hint by the filter created here.
|
||||
*
|
||||
* <p>
|
||||
* Some common simple customizations:
|
||||
* <ul>
|
||||
* <li>Switch off security completely and permanently: remove Spring Security from the
|
||||
* classpath or {@link EnableAutoConfiguration#exclude() exclude} this configuration.</li>
|
||||
* <li>Switch off security temporarily (e.g. for a dev environment): set
|
||||
* <code>security.basic.enabled: false</code></li>
|
||||
* <li>Customize the user details: add an AuthenticationManager bean</li>
|
||||
* <li>Add form login for user facing resources: add a
|
||||
* {@link WebSecurityConfigurerAdapter} and use {@link HttpSecurity#formLogin()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ EnableWebSecurity.class })
|
||||
@EnableWebSecurity
|
||||
@EnableConfigurationProperties
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
@Bean(name = "org.springframework.zero.actuate.properties.SecurityProperties")
|
||||
@ConditionalOnMissingBean
|
||||
public SecurityProperties securityProperties() {
|
||||
return new SecurityProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AuthenticationEventPublisher authenticationEventPublisher() {
|
||||
return new DefaultAuthenticationEventPublisher();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean({ BoostrapWebSecurityConfigurerAdapter.class })
|
||||
public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter() {
|
||||
return new BoostrapWebSecurityConfigurerAdapter();
|
||||
}
|
||||
|
||||
// Give user-supplied filters a chance to be last in line
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 10)
|
||||
private static class BoostrapWebSecurityConfigurerAdapter extends
|
||||
WebSecurityConfigurerAdapter {
|
||||
|
||||
private static final String[] NO_PATHS = new String[0];
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties security;
|
||||
|
||||
@Autowired(required = false)
|
||||
private EndpointHandlerMapping endpointHandlerMapping;
|
||||
|
||||
@Autowired
|
||||
private AuthenticationEventPublisher authenticationEventPublisher;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ErrorController errorController;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
if (this.security.isRequireSsl()) {
|
||||
http.requiresChannel().anyRequest().requiresSecure();
|
||||
}
|
||||
|
||||
if (this.security.getBasic().isEnabled()) {
|
||||
String[] paths = getSecurePaths();
|
||||
http.exceptionHandling().authenticationEntryPoint(entryPoint()).and()
|
||||
.requestMatchers().antMatchers(paths);
|
||||
http.httpBasic().and().anonymous().disable();
|
||||
http.authorizeUrls().anyRequest()
|
||||
.hasRole(this.security.getBasic().getRole());
|
||||
}
|
||||
|
||||
// No cookies for service endpoints by default
|
||||
http.sessionManagement().sessionCreationPolicy(this.security.getSessions());
|
||||
}
|
||||
|
||||
private String[] getSecurePaths() {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (String path : this.security.getBasic().getPath()) {
|
||||
path = (path == null ? "" : path.trim());
|
||||
if (path.equals("/**")) {
|
||||
return new String[] { path };
|
||||
}
|
||||
if (!path.equals("")) {
|
||||
list.add(path);
|
||||
}
|
||||
}
|
||||
// FIXME makes more sense to secure endpoints with a different role
|
||||
list.addAll(Arrays.asList(getEndpointPaths(true)));
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
private AuthenticationEntryPoint entryPoint() {
|
||||
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
|
||||
entryPoint.setRealmName(this.security.getBasic().getRealm());
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity builder) throws Exception {
|
||||
IgnoredRequestConfigurer ignoring = builder.ignoring();
|
||||
ignoring.antMatchers(this.security.getIgnored());
|
||||
ignoring.antMatchers(getEndpointPaths(false));
|
||||
if (this.errorController != null) {
|
||||
ignoring.antMatchers(this.errorController.getErrorPath());
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getEndpointPaths(boolean secure) {
|
||||
if (this.endpointHandlerMapping == null) {
|
||||
return NO_PATHS;
|
||||
}
|
||||
|
||||
// FIXME this will still open up paths on the server when a management port is
|
||||
// being used.
|
||||
|
||||
List<Endpoint<?>> endpoints = this.endpointHandlerMapping.getEndpoints();
|
||||
List<String> paths = new ArrayList<String>(endpoints.size());
|
||||
for (Endpoint<?> endpoint : endpoints) {
|
||||
if (endpoint.isSensitive() == secure) {
|
||||
paths.add(endpoint.getPath());
|
||||
}
|
||||
}
|
||||
return paths.toArray(new String[paths.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
AuthenticationManager manager = super.authenticationManager();
|
||||
if (manager instanceof ProviderManager) {
|
||||
((ProviderManager) manager)
|
||||
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean(AuthenticationManager.class)
|
||||
@Configuration
|
||||
public static class AuthenticationManagerConfiguration {
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() throws Exception {
|
||||
return new AuthenticationManagerBuilder().inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and().and()
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.zero.actuate.trace.InMemoryTraceRepository;
|
||||
import org.springframework.zero.actuate.trace.TraceRepository;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link TraceRepository tracing}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
public class TraceRepositoryAutoConfiguration {
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
public TraceRepository traceRepository() {
|
||||
return new InMemoryTraceRepository();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.autoconfigure;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.zero.actuate.trace.TraceRepository;
|
||||
import org.springframework.zero.actuate.trace.WebRequestTraceFilter;
|
||||
import org.springframework.zero.context.annotation.AutoConfigureAfter;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.annotation.EnableAutoConfiguration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link WebRequestTraceFilter
|
||||
* tracing}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
||||
@AutoConfigureAfter(TraceRepositoryAutoConfiguration.class)
|
||||
public class TraceWebFilterAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private TraceRepository traceRepository;
|
||||
|
||||
@Value("${management.dump_requests:false}")
|
||||
private boolean dumpRequests;
|
||||
|
||||
@Bean
|
||||
public WebRequestTraceFilter webRequestLoggingFilter(BeanFactory beanFactory) {
|
||||
WebRequestTraceFilter filter = new WebRequestTraceFilter(this.traceRepository);
|
||||
filter.setDumpRequests(this.dumpRequests);
|
||||
return filter;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Abstract base for {@link Endpoint} implementations.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
||||
|
||||
private static final MediaType[] NO_MEDIA_TYPES = new MediaType[0];
|
||||
|
||||
@NotNull
|
||||
@Pattern(regexp = "/[^/]*", message = "Path must start with /")
|
||||
private String path;
|
||||
|
||||
private boolean sensitive;
|
||||
|
||||
public AbstractEndpoint(String path) {
|
||||
this(path, true);
|
||||
}
|
||||
|
||||
public AbstractEndpoint(String path, boolean sensitive) {
|
||||
this.path = path;
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType[] getProduces() {
|
||||
return NO_MEDIA_TYPES;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
/**
|
||||
* Tagging interface used to indicate that {@link Endpoint} that performs some action.
|
||||
* Allows mappings to refine the types of request supported.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface ActionEndpoint<T> extends Endpoint<T> {
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.support.LiveBeansView;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Exposes JSON view of Spring beans. If the {@link Environment} contains a key setting
|
||||
* the {@link LiveBeansView#MBEAN_DOMAIN_PROPERTY_NAME} then all application contexts in
|
||||
* the JVM will be shown (and the corresponding MBeans will be registered per the standard
|
||||
* behavior of LiveBeansView). Otherwise only the current application context.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.beans", ignoreUnknownFields = false)
|
||||
public class BeansEndpoint extends AbstractEndpoint<String> implements
|
||||
ApplicationContextAware {
|
||||
|
||||
private LiveBeansView liveBeansView = new LiveBeansView();
|
||||
|
||||
public BeansEndpoint() {
|
||||
super("/beans");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
if (context.getEnvironment()
|
||||
.getProperty(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME) == null) {
|
||||
this.liveBeansView.setApplicationContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType[] getProduces() {
|
||||
return new MediaType[] { MediaType.APPLICATION_JSON };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String invoke() {
|
||||
return this.liveBeansView.getSnapshotAsJson();
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose thread info.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.dump", ignoreUnknownFields = false)
|
||||
public class DumpEndpoint extends AbstractEndpoint<List<ThreadInfo>> {
|
||||
|
||||
/**
|
||||
* Create a new {@link DumpEndpoint} instance.
|
||||
*/
|
||||
public DumpEndpoint() {
|
||||
super("/dump");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThreadInfo> invoke() {
|
||||
return Arrays.asList(ManagementFactory.getThreadMXBean().dumpAllThreads(true,
|
||||
true));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* An endpoint that can be used to expose useful information to operations. Usually
|
||||
* exposed via Spring MVC but could also be exposed using some other technique.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface Endpoint<T> {
|
||||
|
||||
/**
|
||||
* Returns the path of the endpoint. Must start with '/' and should not include
|
||||
* wildcards.
|
||||
*/
|
||||
String getPath();
|
||||
|
||||
/**
|
||||
* Returns if the endpoint is sensitive, i.e. may return data that the average user
|
||||
* should not see. Mappings can use this as a security hint.
|
||||
*/
|
||||
boolean isSensitive();
|
||||
|
||||
/**
|
||||
* Returns the {@link MediaType}s that this endpoint produces or {@code null}.
|
||||
*/
|
||||
MediaType[] getProduces();
|
||||
|
||||
/**
|
||||
* Called to invoke the endpoint.
|
||||
* @return the results of the invocation
|
||||
*/
|
||||
T invoke();
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link ConfigurableEnvironment environment} information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.env", ignoreUnknownFields = false)
|
||||
public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
||||
EnvironmentAware {
|
||||
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Create a new {@link EnvironmentEndpoint} instance.
|
||||
*/
|
||||
public EnvironmentEndpoint() {
|
||||
super("/env");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
for (PropertySource<?> source : getPropertySources()) {
|
||||
if (source instanceof EnumerablePropertySource) {
|
||||
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
for (String name : enumerable.getPropertyNames()) {
|
||||
map.put(name, sanitize(name, enumerable.getProperty(name)));
|
||||
}
|
||||
result.put(source.getName(), map);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Iterable<PropertySource<?>> getPropertySources() {
|
||||
if (this.environment != null
|
||||
&& this.environment instanceof ConfigurableEnvironment) {
|
||||
return ((ConfigurableEnvironment) this.environment).getPropertySources();
|
||||
}
|
||||
return new StandardEnvironment().getPropertySources();
|
||||
}
|
||||
|
||||
private Object sanitize(String name, Object object) {
|
||||
if (name.toLowerCase().endsWith("password")
|
||||
|| name.toLowerCase().endsWith("secret")) {
|
||||
return object == null ? null : "******";
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.zero.actuate.health.HealthIndicator;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose application health.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.health", ignoreUnknownFields = false)
|
||||
public class HealthEndpoint<T> extends AbstractEndpoint<T> {
|
||||
|
||||
private HealthIndicator<? extends T> indicator;
|
||||
|
||||
/**
|
||||
* Create a new {@link HealthIndicator} instance.
|
||||
*
|
||||
* @param indicator the health indicator
|
||||
*/
|
||||
public HealthEndpoint(HealthIndicator<? extends T> indicator) {
|
||||
super("/health", false);
|
||||
Assert.notNull(indicator, "Indicator must not be null");
|
||||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T invoke() {
|
||||
return this.indicator.health();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose arbitrary application information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.info", ignoreUnknownFields = false)
|
||||
public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private Map<String, ? extends Object> info;
|
||||
|
||||
/**
|
||||
* Create a new {@link InfoEndpoint} instance.
|
||||
*
|
||||
* @param info the info to expose
|
||||
*/
|
||||
public InfoEndpoint(Map<String, ? extends Object> info) {
|
||||
super("/info", true);
|
||||
Assert.notNull(info, "Info must not be null");
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>(this.info);
|
||||
info.putAll(getAdditionalInfo());
|
||||
return info;
|
||||
}
|
||||
|
||||
protected Map<String, Object> getAdditionalInfo() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.zero.actuate.metrics.Metric;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link PublicMetrics}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.metrics", ignoreUnknownFields = false)
|
||||
public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private PublicMetrics metrics;
|
||||
|
||||
/**
|
||||
* Create a new {@link MetricsEndpoint} instance.
|
||||
*
|
||||
* @param metrics the metrics to expose
|
||||
*/
|
||||
public MetricsEndpoint(PublicMetrics metrics) {
|
||||
super("/metrics");
|
||||
Assert.notNull(metrics, "Metrics must not be null");
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
for (Metric metric : this.metrics.metrics()) {
|
||||
result.put(metric.getName(), metric.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.zero.actuate.metrics.Metric;
|
||||
|
||||
/**
|
||||
* Interface to expose specific {@link Metric}s via a {@link MetricsEndpoint}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see VanillaPublicMetrics
|
||||
*/
|
||||
public interface PublicMetrics {
|
||||
|
||||
/**
|
||||
* @return an indication of current state through metrics
|
||||
*/
|
||||
Collection<Metric> metrics();
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.zero.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link ActionEndpoint} to shutdown the {@link ApplicationContext}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.shutdown", ignoreUnknownFields = false)
|
||||
public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
||||
ApplicationContextAware, ActionEndpoint<Map<String, Object>> {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ManagementServerProperties configuration = new ManagementServerProperties();
|
||||
|
||||
/**
|
||||
* Create a new {@link ShutdownEndpoint} instance.
|
||||
*/
|
||||
public ShutdownEndpoint() {
|
||||
super("/shutdown");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
if (this.configuration == null || !this.configuration.isAllowShutdown()
|
||||
|| this.context == null) {
|
||||
return Collections.<String, Object> singletonMap("message",
|
||||
"Shutdown not enabled, sorry.");
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(500L);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
ShutdownEndpoint.this.context.close();
|
||||
}
|
||||
}).start();
|
||||
|
||||
return Collections.<String, Object> singletonMap("message",
|
||||
"Shutting down, bye...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
if (context instanceof ConfigurableApplicationContext) {
|
||||
this.context = (ConfigurableApplicationContext) context;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.zero.actuate.trace.Trace;
|
||||
import org.springframework.zero.actuate.trace.TraceRepository;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link Trace} information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.trace", ignoreUnknownFields = false)
|
||||
public class TraceEndpoint extends AbstractEndpoint<List<Trace>> {
|
||||
|
||||
private TraceRepository repository;
|
||||
|
||||
/**
|
||||
* Create a new {@link TraceEndpoint} instance.
|
||||
*
|
||||
* @param repository the trace repository
|
||||
*/
|
||||
public TraceEndpoint(TraceRepository repository) {
|
||||
super("/trace");
|
||||
Assert.notNull(repository, "Repository must not be null");
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Trace> invoke() {
|
||||
return this.repository.findAll();
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.zero.actuate.metrics.Metric;
|
||||
import org.springframework.zero.actuate.metrics.MetricRepository;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link PublicMetrics} that exposes all metrics from the
|
||||
* {@link MetricRepository} along with memory information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VanillaPublicMetrics implements PublicMetrics {
|
||||
|
||||
private MetricRepository metricRepository;
|
||||
|
||||
public VanillaPublicMetrics(MetricRepository metricRepository) {
|
||||
Assert.notNull(metricRepository, "MetricRepository must not be null");
|
||||
this.metricRepository = metricRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Metric> metrics() {
|
||||
Collection<Metric> result = new LinkedHashSet<Metric>(
|
||||
this.metricRepository.findAll());
|
||||
result.add(new Metric("mem", new Long(Runtime.getRuntime().totalMemory()) / 1024));
|
||||
result.add(new Metric("mem.free",
|
||||
new Long(Runtime.getRuntime().freeMemory()) / 1024));
|
||||
result.add(new Metric("processors", Runtime.getRuntime().availableProcessors()));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor;
|
||||
import org.springframework.zero.actuate.endpoint.Endpoint;
|
||||
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
/**
|
||||
* MVC {@link HandlerAdapter} for {@link Endpoint}s. Similar in may respects to
|
||||
* {@link AbstractMessageConverterMethodProcessor} but not tied to annotated methods.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see EndpointHandlerMapping
|
||||
*/
|
||||
public class EndpointHandlerAdapter implements HandlerAdapter {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(EndpointHandlerAdapter.class);
|
||||
|
||||
private static final MediaType MEDIA_TYPE_APPLICATION = new MediaType("application");
|
||||
|
||||
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
|
||||
|
||||
private List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
private List<MediaType> allSupportedMediaTypes;
|
||||
|
||||
public EndpointHandlerAdapter() {
|
||||
WebMvcConfigurationSupportConventions conventions = new WebMvcConfigurationSupportConventions();
|
||||
setMessageConverters(conventions.getDefaultHttpMessageConverters());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Object handler) {
|
||||
return handler instanceof Endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified(HttpServletRequest request, Object handler) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
handle(request, response, (Endpoint<?>) handler);
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
Endpoint<?> endpoint) throws Exception {
|
||||
|
||||
Object result = endpoint.invoke();
|
||||
Class<?> resultClass = result.getClass();
|
||||
|
||||
List<MediaType> mediaTypes = getMediaTypes(request, endpoint, resultClass);
|
||||
MediaType selectedMediaType = selectMediaType(mediaTypes);
|
||||
|
||||
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
|
||||
try {
|
||||
if (selectedMediaType != null) {
|
||||
selectedMediaType = selectedMediaType.removeQualityValue();
|
||||
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
|
||||
if (messageConverter.canWrite(resultClass, selectedMediaType)) {
|
||||
((HttpMessageConverter<Object>) messageConverter).write(result,
|
||||
selectedMediaType, outputMessage);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Written [" + result + "] as \""
|
||||
+ selectedMediaType + "\" using [" + messageConverter
|
||||
+ "]");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
|
||||
} finally {
|
||||
outputMessage.close();
|
||||
}
|
||||
}
|
||||
|
||||
private List<MediaType> getMediaTypes(HttpServletRequest request,
|
||||
Endpoint<?> endpoint, Class<?> resultClass)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
List<MediaType> requested = getAcceptableMediaTypes(request);
|
||||
List<MediaType> producible = getProducibleMediaTypes(endpoint, resultClass);
|
||||
|
||||
Set<MediaType> compatible = new LinkedHashSet<MediaType>();
|
||||
for (MediaType r : requested) {
|
||||
for (MediaType p : producible) {
|
||||
if (r.isCompatibleWith(p)) {
|
||||
compatible.add(getMostSpecificMediaType(r, p));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (compatible.isEmpty()) {
|
||||
throw new HttpMediaTypeNotAcceptableException(producible);
|
||||
}
|
||||
List<MediaType> mediaTypes = new ArrayList<MediaType>(compatible);
|
||||
MediaType.sortBySpecificityAndQuality(mediaTypes);
|
||||
return mediaTypes;
|
||||
}
|
||||
|
||||
private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
List<MediaType> mediaTypes = this.contentNegotiationManager
|
||||
.resolveMediaTypes(new ServletWebRequest(request));
|
||||
return mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL)
|
||||
: mediaTypes;
|
||||
}
|
||||
|
||||
private List<MediaType> getProducibleMediaTypes(Endpoint<?> endpoint,
|
||||
Class<?> returnValueClass) {
|
||||
MediaType[] mediaTypes = endpoint.getProduces();
|
||||
if (mediaTypes != null && mediaTypes.length != 0) {
|
||||
return Arrays.asList(mediaTypes);
|
||||
}
|
||||
|
||||
if (this.allSupportedMediaTypes.isEmpty()) {
|
||||
return Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
|
||||
List<MediaType> result = new ArrayList<MediaType>();
|
||||
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||
if (converter.canWrite(returnValueClass, null)) {
|
||||
result.addAll(converter.getSupportedMediaTypes());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
||||
produceType = produceType.copyQualityValue(acceptType);
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) <= 0 ? acceptType
|
||||
: produceType;
|
||||
}
|
||||
|
||||
private MediaType selectMediaType(List<MediaType> mediaTypes) {
|
||||
MediaType selectedMediaType = null;
|
||||
for (MediaType mediaType : mediaTypes) {
|
||||
if (mediaType.isConcrete()) {
|
||||
selectedMediaType = mediaType;
|
||||
break;
|
||||
} else if (mediaType.equals(MediaType.ALL)
|
||||
|| mediaType.equals(MEDIA_TYPE_APPLICATION)) {
|
||||
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return selectedMediaType;
|
||||
}
|
||||
|
||||
public void setContentNegotiationManager(
|
||||
ContentNegotiationManager contentNegotiationManager) {
|
||||
this.contentNegotiationManager = contentNegotiationManager;
|
||||
}
|
||||
|
||||
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||
this.messageConverters = messageConverters;
|
||||
Set<MediaType> allSupportedMediaTypes = new LinkedHashSet<MediaType>();
|
||||
for (HttpMessageConverter<?> messageConverter : messageConverters) {
|
||||
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
|
||||
}
|
||||
this.allSupportedMediaTypes = new ArrayList<MediaType>(allSupportedMediaTypes);
|
||||
MediaType.sortBySpecificity(this.allSupportedMediaTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default conventions, taken from {@link WebMvcConfigurationSupport} with a few minor
|
||||
* tweaks.
|
||||
*/
|
||||
private static class WebMvcConfigurationSupportConventions extends
|
||||
WebMvcConfigurationSupport {
|
||||
public List<HttpMessageConverter<?>> getDefaultHttpMessageConverters() {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
addDefaultHttpMessageConverters(converters);
|
||||
for (HttpMessageConverter<?> converter : converters) {
|
||||
if (converter instanceof MappingJackson2HttpMessageConverter) {
|
||||
MappingJackson2HttpMessageConverter jacksonConverter = (MappingJackson2HttpMessageConverter) converter;
|
||||
jacksonConverter.getObjectMapper().disable(
|
||||
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
}
|
||||
}
|
||||
return converters;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
|
||||
import org.springframework.zero.actuate.endpoint.ActionEndpoint;
|
||||
import org.springframework.zero.actuate.endpoint.Endpoint;
|
||||
|
||||
/**
|
||||
* {@link HandlerMapping} to map {@link Endpoint}s to URLs via {@link Endpoint#getPath()}.
|
||||
* Standard {@link Endpoint}s are mapped to GET requests, {@link ActionEndpoint}s are
|
||||
* mapped to POST requests.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see EndpointHandlerAdapter
|
||||
*/
|
||||
public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||
InitializingBean, ApplicationContextAware {
|
||||
|
||||
private List<Endpoint<?>> endpoints;
|
||||
|
||||
private String prefix = "";
|
||||
|
||||
private boolean disabled = false;
|
||||
|
||||
/**
|
||||
* Create a new {@link EndpointHandlerMapping} instance. All {@link Endpoint}s will be
|
||||
* detected from the {@link ApplicationContext}.
|
||||
*/
|
||||
public EndpointHandlerMapping() {
|
||||
setOrder(HIGHEST_PRECEDENCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link EndpointHandlerMapping} with the specified endpoints.
|
||||
* @param endpoints the endpoints
|
||||
*/
|
||||
public EndpointHandlerMapping(Collection<? extends Endpoint<?>> endpoints) {
|
||||
Assert.notNull(endpoints, "Endpoints must not be null");
|
||||
this.endpoints = new ArrayList<Endpoint<?>>(endpoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (this.endpoints == null) {
|
||||
this.endpoints = findEndpointBeans();
|
||||
}
|
||||
if (!this.disabled) {
|
||||
for (Endpoint<?> endpoint : this.endpoints) {
|
||||
registerHandler(this.prefix + endpoint.getPath(), endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private List<Endpoint<?>> findEndpointBeans() {
|
||||
return new ArrayList(BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
getApplicationContext(), Endpoint.class).values());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object lookupHandler(String urlPath, HttpServletRequest request)
|
||||
throws Exception {
|
||||
Object handler = super.lookupHandler(urlPath, request);
|
||||
if (handler != null) {
|
||||
Object endpoint = (handler instanceof HandlerExecutionChain ? ((HandlerExecutionChain) handler)
|
||||
.getHandler() : handler);
|
||||
String method = (endpoint instanceof ActionEndpoint<?> ? "POST" : "GET");
|
||||
if (request.getMethod().equals(method)) {
|
||||
return endpoint;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prefix the prefix to set
|
||||
*/
|
||||
public void setPrefix(String prefix) {
|
||||
Assert.isTrue("".equals(prefix) || StringUtils.startsWithIgnoreCase(prefix, "/"),
|
||||
"prefix must start with '/'");
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if this mapping is disabled.
|
||||
*/
|
||||
public void setDisabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this mapping is disabled.
|
||||
*/
|
||||
public boolean isDisabled() {
|
||||
return this.disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the endpoints
|
||||
*/
|
||||
public List<Endpoint<?>> getEndpoints() {
|
||||
return Collections.unmodifiableList(this.endpoints);
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.fixme;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.zero.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.zero.actuate.web.BasicErrorController;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnBean;
|
||||
import org.springframework.zero.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.zero.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.zero.context.embedded.ErrorPage;
|
||||
import org.springframework.zero.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
import org.springframework.zero.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
|
||||
/**
|
||||
* Configuration for creating a new container (e.g. tomcat) for the management endpoints.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@Import(ManagementSecurityConfiguration.class)
|
||||
public class ManagementServerConfiguration {
|
||||
|
||||
// FIXME delete when security works
|
||||
|
||||
@Bean
|
||||
public DispatcherServlet dispatcherServlet() {
|
||||
return new DispatcherServlet();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(
|
||||
ApplicationContext context) {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BasicErrorController errorEndpoint() {
|
||||
return new BasicErrorController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(TomcatEmbeddedServletContainerFactory.class)
|
||||
public EmbeddedServletContainerFactory tomcatContainer(
|
||||
HierarchicalBeanFactory beanFactory) {
|
||||
TomcatEmbeddedServletContainerFactory factory = beanFactory
|
||||
.getParentBeanFactory().getBean(
|
||||
TomcatEmbeddedServletContainerFactory.class);
|
||||
return factory.getChildContextFactory("Management");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(JettyEmbeddedServletContainerFactory.class)
|
||||
public EmbeddedServletContainerFactory jettyContainer() {
|
||||
return new JettyEmbeddedServletContainerFactory();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class ServerCustomizationConfiguration implements
|
||||
EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Value("${endpoints.error.path:/error}")
|
||||
private String errorPath = "/error";
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext beanFactory;
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
ManagementServerProperties configuration = this.beanFactory
|
||||
.getBean(ManagementServerProperties.class);
|
||||
factory.setPort(configuration.getPort());
|
||||
factory.setAddress(configuration.getAddress());
|
||||
factory.setContextPath(configuration.getContextPath());
|
||||
factory.addErrorPages(new ErrorPage(this.errorPath));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(name = {
|
||||
"org.springframework.security.config.annotation.web.EnableWebSecurity",
|
||||
"javax.servlet.Filter" })
|
||||
class ManagementSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
// TODO: enable and get rid of the empty filter when @ConditionalOnBean works
|
||||
// @ConditionalOnBean(name = "springSecurityFilterChain")
|
||||
public Filter springSecurityFilterChain(HierarchicalBeanFactory beanFactory) {
|
||||
BeanFactory parent = beanFactory.getParentBeanFactory();
|
||||
if (parent != null && parent.containsBean("springSecurityFilterChain")) {
|
||||
return parent.getBean("springSecurityFilterChain", Filter.class);
|
||||
}
|
||||
return new GenericFilterBean() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.health;
|
||||
|
||||
/**
|
||||
* Strategy interface used to provide an indication of application health.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see VanillaHealthIndicator
|
||||
*/
|
||||
public interface HealthIndicator<T> {
|
||||
|
||||
/**
|
||||
* @return an indication of health
|
||||
*/
|
||||
T health();
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.health;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link HealthIndicator} that simply returns "ok".
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VanillaHealthIndicator implements HealthIndicator<String> {
|
||||
|
||||
@Override
|
||||
public String health() {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
/**
|
||||
* A service that can be used to increment, decrement and reset a {@link Metric}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface CounterService {
|
||||
|
||||
/**
|
||||
* Increment the specified metric by 1.
|
||||
* @param metricName the name of the metric
|
||||
*/
|
||||
void increment(String metricName);
|
||||
|
||||
/**
|
||||
* Decrement the specified metric by 1.
|
||||
* @param metricName the name of the metric
|
||||
*/
|
||||
void decrement(String metricName);
|
||||
|
||||
/**
|
||||
* Reset the specified metric to 0.
|
||||
* @param metricName the name of the metric
|
||||
*/
|
||||
void reset(String metricName);
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link CounterService}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class DefaultCounterService implements CounterService {
|
||||
|
||||
private MetricRepository repository;
|
||||
|
||||
/**
|
||||
* Create a {@link DefaultCounterService} instance.
|
||||
* @param repository the underlying repository used to manage metrics
|
||||
*/
|
||||
public DefaultCounterService(MetricRepository repository) {
|
||||
super();
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(String metricName) {
|
||||
this.repository.increment(wrap(metricName), 1, new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrement(String metricName) {
|
||||
this.repository.increment(wrap(metricName), -1, new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(String metricName) {
|
||||
this.repository.set(wrap(metricName), 0, new Date());
|
||||
}
|
||||
|
||||
private String wrap(String metricName) {
|
||||
if (metricName.startsWith("counter")) {
|
||||
return metricName;
|
||||
} else {
|
||||
return "counter." + metricName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link GaugeService}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class DefaultGaugeService implements GaugeService {
|
||||
|
||||
private MetricRepository metricRepository;
|
||||
|
||||
/**
|
||||
* @param counterRepository
|
||||
*/
|
||||
public DefaultGaugeService(MetricRepository counterRepository) {
|
||||
super();
|
||||
this.metricRepository = counterRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String metricName, double value) {
|
||||
this.metricRepository.set(wrap(metricName), value, new Date());
|
||||
}
|
||||
|
||||
private String wrap(String metricName) {
|
||||
if (metricName.startsWith("gauge")) {
|
||||
return metricName;
|
||||
} else {
|
||||
return "gauge." + metricName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
/**
|
||||
* A service that can be used to manage a {@link Metric} as a gauge.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface GaugeService {
|
||||
|
||||
/**
|
||||
* Set the specified metric value
|
||||
* @param metricName the metric to set
|
||||
* @param value the value of the metric
|
||||
*/
|
||||
void set(String metricName, double value);
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class InMemoryMetricRepository implements MetricRepository {
|
||||
|
||||
private ConcurrentMap<String, Measurement> metrics = new ConcurrentHashMap<String, Measurement>();
|
||||
|
||||
@Override
|
||||
public void increment(String metricName, int amount, Date timestamp) {
|
||||
// FIXME this might not be thread safe
|
||||
Measurement current = this.metrics.get(metricName);
|
||||
if (current != null) {
|
||||
Metric metric = current.getMetric();
|
||||
this.metrics.replace(metricName, current,
|
||||
new Measurement(timestamp, metric.increment(amount)));
|
||||
} else {
|
||||
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric(
|
||||
metricName, amount)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String metricName, double value, Date timestamp) {
|
||||
Measurement current = this.metrics.get(metricName);
|
||||
if (current != null) {
|
||||
Metric metric = current.getMetric();
|
||||
this.metrics.replace(metricName, current,
|
||||
new Measurement(timestamp, metric.set(value)));
|
||||
} else {
|
||||
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric(
|
||||
metricName, value)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String metricName) {
|
||||
this.metrics.remove(metricName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metric findOne(String metricName) {
|
||||
if (this.metrics.containsKey(metricName)) {
|
||||
return this.metrics.get(metricName).getMetric();
|
||||
}
|
||||
return new Metric(metricName, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Metric> findAll() {
|
||||
ArrayList<Metric> result = new ArrayList<Metric>();
|
||||
for (Measurement measurement : this.metrics.values()) {
|
||||
result.add(measurement.getMetric());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A {@link Metric} at a given point in time.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public final class Measurement {
|
||||
|
||||
private Date timestamp;
|
||||
|
||||
private Metric metric;
|
||||
|
||||
public Measurement(Date timestamp, Metric metric) {
|
||||
this.timestamp = timestamp;
|
||||
this.metric = metric;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
public Metric getMetric() {
|
||||
return this.metric;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Measurement [dateTime=" + this.timestamp + ", metric=" + this.metric
|
||||
+ "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.timestamp);
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.metric);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() == obj.getClass()) {
|
||||
Measurement other = (Measurement) obj;
|
||||
boolean result = ObjectUtils.nullSafeEquals(this.timestamp, other.timestamp);
|
||||
result &= ObjectUtils.nullSafeEquals(this.metric, other.metric);
|
||||
return result;
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Immutable class that can be used to hold any arbitrary system measurement value. For
|
||||
* example a metric might record the number of active connections.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see MetricRepository
|
||||
* @see CounterService
|
||||
*/
|
||||
public final class Metric {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final double value;
|
||||
|
||||
/**
|
||||
* Create a new {@link Metric} instance.
|
||||
* @param name the name of the metric
|
||||
* @param value the value of the metric
|
||||
*/
|
||||
public Metric(String name, double value) {
|
||||
super();
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the metric.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the metric.
|
||||
*/
|
||||
public double getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Metric} with an incremented value.
|
||||
* @param amount the amount that the new metric will differ from this one
|
||||
* @return a new {@link Metric} instance
|
||||
*/
|
||||
public Metric increment(int amount) {
|
||||
return new Metric(this.name, new Double(((int) this.value) + amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Metric} with a different value.
|
||||
* @param value the value of the new metric
|
||||
* @return a new {@link Metric} instance
|
||||
*/
|
||||
public Metric set(double value) {
|
||||
return new Metric(this.name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Metric [name=" + this.name + ", value=" + this.value + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int valueHashCode = ObjectUtils.hashCode(this.value);
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
result = prime * result + (valueHashCode ^ (valueHashCode >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() == obj.getClass()) {
|
||||
Metric other = (Metric) obj;
|
||||
boolean result = ObjectUtils.nullSafeEquals(this.name, other.name);
|
||||
result &= Double.doubleToLongBits(this.value) == Double
|
||||
.doubleToLongBits(other.value);
|
||||
return result;
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.metrics;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* A Repository used to manage {@link Metric}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface MetricRepository {
|
||||
|
||||
// FIXME perhaps revisit this, there is no way to get timestamps
|
||||
// could also simply, leaving increment to counter service
|
||||
|
||||
// Perhaps findAll, findOne should return Measurements
|
||||
// put(String name, Callback -> process(Metric)
|
||||
|
||||
void increment(String metricName, int amount, Date timestamp);
|
||||
|
||||
void set(String metricName, double value, Date timestamp);
|
||||
|
||||
void delete(String metricName);
|
||||
|
||||
Metric findOne(String metricName);
|
||||
|
||||
Collection<Metric> findAll();
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.properties;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.zero.properties.ServerProperties;
|
||||
|
||||
/**
|
||||
* Properties for the management server (e.g. port and path settings).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see ServerProperties
|
||||
*/
|
||||
@ConfigurationProperties(name = "management", ignoreUnknownFields = false)
|
||||
public class ManagementServerProperties {
|
||||
|
||||
private Integer port;
|
||||
|
||||
private InetAddress address;
|
||||
|
||||
@NotNull
|
||||
private String contextPath = "";
|
||||
|
||||
private boolean allowShutdown = false;
|
||||
|
||||
public boolean isAllowShutdown() {
|
||||
return this.allowShutdown;
|
||||
}
|
||||
|
||||
public void setAllowShutdown(boolean allowShutdown) {
|
||||
this.allowShutdown = allowShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the management port or {@code null} if the
|
||||
* {@link ServerProperties#getPort() server port} should be used.
|
||||
* @see #setPort(Integer)
|
||||
*/
|
||||
public Integer getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the port of the management server, use {@code null} if the
|
||||
* {@link ServerProperties#getPort() server port} should be used. To disable use 0.
|
||||
*/
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public InetAddress getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public void setAddress(InetAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getContextPath() {
|
||||
return this.contextPath;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.properties;
|
||||
|
||||
import org.springframework.security.config.annotation.web.configurers.SessionCreationPolicy;
|
||||
import org.springframework.zero.context.annotation.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for the security aspects of an application.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "security", ignoreUnknownFields = false)
|
||||
public class SecurityProperties {
|
||||
|
||||
private boolean requireSsl;
|
||||
|
||||
private Basic basic = new Basic();
|
||||
|
||||
private SessionCreationPolicy sessions = SessionCreationPolicy.stateless;
|
||||
|
||||
private String[] ignored = new String[] { "/css/**", "/js/**", "/images/**",
|
||||
"/**/favicon.ico" };
|
||||
|
||||
public SessionCreationPolicy getSessions() {
|
||||
return this.sessions;
|
||||
}
|
||||
|
||||
public void setSessions(SessionCreationPolicy sessions) {
|
||||
this.sessions = sessions;
|
||||
}
|
||||
|
||||
public Basic getBasic() {
|
||||
return this.basic;
|
||||
}
|
||||
|
||||
public void setBasic(Basic basic) {
|
||||
this.basic = basic;
|
||||
}
|
||||
|
||||
public boolean isRequireSsl() {
|
||||
return this.requireSsl;
|
||||
}
|
||||
|
||||
public void setRequireSsl(boolean requireSsl) {
|
||||
this.requireSsl = requireSsl;
|
||||
}
|
||||
|
||||
public void setIgnored(String... ignored) {
|
||||
this.ignored = ignored;
|
||||
}
|
||||
|
||||
public String[] getIgnored() {
|
||||
return this.ignored;
|
||||
}
|
||||
|
||||
public static class Basic {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
private String realm = "Spring";
|
||||
|
||||
private String[] path = new String[] { "/**" };
|
||||
|
||||
private String role = "USER";
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return this.realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String[] getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String... paths) {
|
||||
this.path = paths;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return this.role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.zero.actuate.security;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
|
||||
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
|
||||
import org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent;
|
||||
import org.springframework.zero.actuate.audit.AuditEvent;
|
||||
import org.springframework.zero.actuate.audit.listener.AuditApplicationEvent;
|
||||
|
||||
/**
|
||||
* {@link ApplicationListener} expose Spring Security {@link AbstractAuthenticationEvent
|
||||
* authentication events} as {@link AuditEvent}s.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuthenticationAuditListener implements
|
||||
ApplicationListener<AbstractAuthenticationEvent>, ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractAuthenticationEvent event) {
|
||||
if (event instanceof AbstractAuthenticationFailureEvent) {
|
||||
onAuthenticationFailureEvent((AbstractAuthenticationFailureEvent) event);
|
||||
} else if (event instanceof AuthenticationSwitchUserEvent) {
|
||||
onAuthenticationSwitchUserEvent((AuthenticationSwitchUserEvent) event);
|
||||
} else {
|
||||
onAuthenticationEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAuthenticationFailureEvent(AbstractAuthenticationFailureEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("type", event.getException().getClass().getName());
|
||||
data.put("message", event.getException().getMessage());
|
||||
publish(new AuditEvent(event.getAuthentication().getName(),
|
||||
"AUTHENTICATION_FAILURE", data));
|
||||
}
|
||||
|
||||
private void onAuthenticationSwitchUserEvent(AuthenticationSwitchUserEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
if (event.getAuthentication().getDetails() != null) {
|
||||
data.put("details", event.getAuthentication().getDetails());
|
||||
}
|
||||
data.put("target", event.getTargetUser().getUsername());
|
||||
publish(new AuditEvent(event.getAuthentication().getName(),
|
||||
"AUTHENTICATION_SWITCH", data));
|
||||
}
|
||||
|
||||
private void onAuthenticationEvent(AbstractAuthenticationEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
if (event.getAuthentication().getDetails() != null) {
|
||||
data.put("details", event.getAuthentication().getDetails());
|
||||
}
|
||||
publish(new AuditEvent(event.getAuthentication().getName(),
|
||||
"AUTHENTICATION_SUCCESS", data));
|
||||
}
|
||||
|
||||
private void publish(AuditEvent event) {
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(new AuditApplicationEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue