В продолжении поста чирикает и Facebook поста , позволяет нам расширить OAuth службу , чтобы позволить нам статус обновления на Linkedin. Мы начинаем с создания LinkedinService
Так вот, сервис Linkedin
//interface
public interface LinkedinService extends BaseOAuthService {
}
//implementation
public class LinkedinServiceImpl extends BaseOAuthServiceImpl implements LinkedinService {
private ApplicationStateManager stateManager;
public LinkedinServiceImpl(OAuthConfiguration configuration, String apiPrefix,
ApplicationStateManager stateManager) {
super(configuration, LinkedInApi.class, apiPrefix);
this.stateManager = stateManager;
}
@Override
public String getAuthorizationURL() {
Token requestToken = newRequestToken();
stateManager.set(Token.class, requestToken);
return getOAuthService().getAuthorizationUrl(requestToken);
}
@Override
public Token requestAccessToken(String oauthToken, String verifier) {
Token requestToken = stateManager.getIfExists(Token.class);
return getOAuthService().getAccessToken(requestToken, new Verifier(verifier));
}
}
Linkedin использует токен запроса для получения токена доступа. Это требует от нас сохранения токена запроса в сеансе пользователя с помощью ApplicationStateManager. Далее идет OAuthResource для обновления статуса Linkedin.
public class LinkedinStatusUpdate extends AbstractOAuthResource {
private String text;
private String title;
private String link;
private String imageLink;
public LinkedinStatusUpdate(Token accessToken,
String text, String title, String link, String imageLink) {
super(accessToken, Verb.POST, "people/~/shares");
this.text = text;
this.title = title;
this.link = link;
this.imageLink = imageLink;
}
@Override
public void process(Response response) {
}
@Override
public void initialize(OAuthRequest request) {
Document doc = new Document();
Element share = doc.newRootElement("share");
if(text != null) {
share.element("comment").text(text);
}
Element content = share.element("content");
if(title != null) {
content.element("title").text(title);
}
if(link != null) {
content.element("submitted-url").text(link);
}
if(imageLink != null) {
content.element("submitted-image-url").text(imageLink);
}
share.element("visibility").element("code").text("anyone");
String requestXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
doc.toString();
request.addHeader("Content-Length", Integer.toString(requestXML.length()));
request.addHeader("Content-Type", "text/xml");
request.addPayload(requestXML);
}
}
Это обновление посвящено отправке xml с информацией о статусе в виде запроса POST людям / ~ / shares. например
<?xml version="1.0" encoding="UTF-8"?> <share> <comment>83% of employers will use social media to hire: 78% LinkedIn, 55% Facebook, 45% Twitter [SF Biz Times] http://bit.ly/cCpeOD</comment> <content> <title>Survey: Social networks top hiring tool - San Francisco Business Times</title> <submitted-url>http://sanfrancisco.bizjournals.com/sanfrancisco/stories/2010/06/28/daily34.html</submitted-url> <submitted-image-url>http://images.bizjournals.com/travel/cityscapes/thumbs/sm_sanfrancisco.jpg</submitted-image-url> </content> <visibility> <code>anyone</code> </visibility> </share>
Этот пример взят со страницы Share Share . Мы используем собственные классы DOM Tapestry для создания XML.
Наконец компонент
@Events( {OAuthConstants.CONNECTION_ESTABLISHED, OAuthConstants.CONNECTION_FAILED})
public class LinkedinConnect implements ClientElement {
@Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL, allowNull = false)
private String clientId;
private String assignedClientId;
@Inject
private JavaScriptSupport javaScriptSupport;
@Inject
private ComponentResources resources;
@Inject
private LinkedinService linkedinService;
@AfterRender
void addJavaScript() {
assignedClientId = javaScriptSupport.allocateClientId(clientId);
}
@OnEvent("connectToLinkedin")
URL getAuthorizationURL() throws MalformedURLException {
return new URL(linkedinService.getAuthorizationURL());
}
Object onAuthorize(
@RequestParameter(value = "oauth_verifier", allowBlank = true) final String verifier,
@RequestParameter(value = "oauth_token", allowBlank = true) String oAuthToken,
@RequestParameter(value = "denied", allowBlank = true) String denied) {
if(verifier != null) {
return accessGranted(oAuthToken, verifier);
} else {
return accessDenied(denied);
}
}
private Object accessGranted(String oAuthToken, String verifier) {
Token accessToken = linkedinService.requestAccessToken(oAuthToken, verifier);
CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>();
boolean handled = resources.triggerEvent(OAuthConstants.CONNECTION_ESTABLISHED, new Object[] {
accessToken}, callback);
if(handled) {
return callback.getResult();
}
return null;
}
private Object accessDenied(String denied) {
CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>();
boolean handled = resources.triggerEvent(OAuthConstants.CONNECTION_FAILED,
new Object[] {denied}, callback);
if(handled) {
return callback.getResult();
}
return null;
}
@Override
public String getClientId() {
return assignedClientId;
}
}
<t:container xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'>
<a href='#' t:type='eventLink' t:event='connectToLinkedin'>
<t:body/>
</a>
</t:container>
Это почти копия TwitterConnect. При щелчке по ссылке обработчик события возвращает URL-адрес авторизации, который перенаправляет браузер на авторизацию Linkedin. После авторизации Linkedin перенаправляет браузер по URL-адресу обратного вызова (указанному в конфигурации), который является нашим обработчиком события onAuthorize (). Обработчик событий, основываясь на параметрах запроса, решает, какой обратный вызов вызвать.
Наконец, вклад модуля
public LinkedinService buildLinkedinService(ApplicationStateManager stateManager){
OAuthConfiguration configurer = new OAuthConfiguration("app_id",
"secret",
"http://localhost:9090/linkedin.linkedinconnect:authorize", null);
return new LinkedinServiceImpl(configurer, OAuthConstants.DEFAULT_LINKEDIN_API_PREFIX, stateManager);
}
Использование компонента на странице очень похоже на предыдущий
public class Linkedin {
@Inject
private LinkedinService linkedinService;
@SuppressWarnings("unused")
@Property
@Persist(PersistenceConstants.FLASH)
private String message;
@OnEvent(value = OAuthConstants.CONNECTION_ESTABLISHED)
void changeStatus(Token accessToken) {
linkedinService.send(new LinkedinStatusUpdate(accessToken, "Google", "Google", "http://www.google.com",
"http://www.google.co.in/intl/en_ALL/images/logos/images_logo_lg.gif"));
message = "Status Updated";
}
void onConnectionFailed(String denied) {
message = "Failed";
}
}
<html xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'>
<body>
${message}<br/>
<a t:id='linkedinConnect' t:type='linkedinConnect'>Connect to Linkedin</a>
</body>
</html>